One thing that I think I forgot to mention is WHAT you can validate against with the EventValidation Action Pack. I thought I would write up a little guide about what you can validate against and even better, how you can extend the validation object to validate against something that is custom.
The current event data check rules that you can apply are as follows:
Specific EventValidator rules:
- required: That the field must be in the event and that it must have some length
- equals: This is a handy function, you can check whether one field equals another, or that a field equals a value, for example to check that the password field matches the password_confirm field we would add this entry in the validation bean:
"The field #rule.getField()# must equal #rule.getValue()#."
So, we can override the default error message as follows: - lessthan/morethan: That the field value is less/more than the value set (such as "you must be over 18 and under 400 to enter this site")
- maxlength/minlength: The length of the field value is more/less than the value set (such as "your password must be between 40 and 60 characters long")
ColdFusion supplied validation rules: EventValidator uses the isValid function and a lot of the in-built ColdFusion validations, these are (I wont list documentation individually, check the Livedocs for details): boolean,creditcard,date,time,email,eurodate,float,numeric,guid,integer,ssn,social_security_number,string,telephone,url,uuid,usdate,xml,zipcode
Creating your own validations
But what about a validation that needs to contact a database or do some other kind of processing that is specific for your system? Well, these are easy to implement. Lets take an example where a user cannot register with a username that has already been taken, which means that I shall need to go into the database to check this.
First step is to create my own validation component, that extends “EventValidation.model.EventValidator” and overriding the “validateEvent” method, then add a loop through the validation rules and creating my own type of validation, here is a quick example:
<cffunction name="validateEvent" returntype="void" access="public" output="false">
<cfargument name="event" type="any" required="true">
<cfargument name="context" type="string" required="true">
<!--- Call the normal validations --->
<cfset super(arguments.event, arguments.context)>
<!--- Loop through the validations --->
<cfloop from="1" to="#ArrayLen(variables.ValidationMap)#" index="r">
<!--- Setup defaults for each validation --->
<cfset rule = CreateObject("component", "Rule").init(variables.ValidationMapr])>
<cfswitch expression="#UCase(rule.getRule())#">
<!--- our own validation --->
<cfcase value="usernotexists">
<!---
Go get the user from the db
Of course, this might be a service or interacting with your own ORM
--->
<cfquery name="getUser">
SELECT userid FROM Users WHERE username = <cfqueryparam cfsqltype="cf_sql_varchar" value="#Trim(event.getValue(rule.getField()))#">
</cfquery>
<cfif getUser.recordcount>
<cfset event.getValue("ErrorCollection").addError(rule, "The Username #event.valueExists(rule.getField())# has already been taken")>
</cfif>
</cfcase>
</cfswitch>
</cfloop>
</cffunction>
</cfcomponent>
</code>
Hopefully the comments in the code above explain what is going on, but essentially you are calling super() to let all the previous validations work, and then we loop through the validationMap which contains our entries and create a rule object for each entry, we then use a switch (you dont have to, but I might be extending this to have a whole bunch of user based validations) with an entry for “usernotexists”, my new validation rule. I then do a query and check it against the username and if it is found, I add an error to the ErrorCollection.
The next step is to setup my bean, as you would do normally but instead of using “EventValidation.model.EventValidator” I use my extended class:
<map>
And there you have it, you have now checked your username against your specific database. Now you can add all sorts of validations that are specific to your own systems!
Tweet
comments powered by Disqus