Up to now the validation support consisted of four constants (VALID_NOT_EMPTY, VALID_NUMBER, VALID_EMAIL, and VALID_YEAR), everything else you had to do yourself. The new validation class in CakePHP 1.2 is a bit more powerful ;-)
The aforementioned constants still work in 1.2, but they are deprecated, so for new code you shouldn’t use them. The usage of the new validation rules follows the following pattern (in your model):
var $validate = array('field' => array('rule' => array('validationmethod', 'param1', 'param2')));
Ok, let’s have a look at the validation methods.
alphaNumeric should be self-explanatory, it allows only letters and strings. Useful for e.g. user names:
var $validate = array('username' => array('rule' => array('alphaNumeric')));
between is a bit misleading, as I expected that it checks whether a number is in a certain range. But what it actually does is to check the string length. In the following example the length of the user name must be at least 3 characters, and maximal 10 characters:
var $validate = array('username' => array('rule' => array('between', 3, 10)));
blank validates that a field is blank or contains only whitespace characters like tabs or spaces. It doesn’t look very useful to me. Its usage is:
var $validate = array('x' => array('rule' => array('blank')));
cc doesn’t stand for “carbon copy”, it stands for “credit card”. It checks whether a credit card number is valid. If you want to check for Visa numbers, you would do the following:
var $validate = array('creditcard' => array('rule' => array('cc', array('visa'))));
comparison is used to compare numeric values. It supports “is greater”, “is less”, “greater or equal”, “less or equal”, “is less”, “equal to”, and “not equal”. To check whether the provided age was higher than 18 you would do:
var $validate = array('age' => array('rule' => array('comparison', '>=', 18)));
or
var $validate = array('age' => array('rule' => array('comparison', 'greater or equal', 18)));
custom is also a bit misleading imho. It allows you to define a regular expression.
var $validate = array('username' => array('rule' => array('custom', '/^[0-9a-z]+$/i')));
date checks for a valid date. It allows different formats, see the API for details. To check whether the entered date is of the format yyyy-mm-dd resp. yy-mm-dd you would do:
var $validate = array('startdate' => array('rule' => array('date', 'ymd')));
decimal checks for a valid decimal number. If you want to have decimal numbers with two digits after the dot you have to use:
var $validate = array('price' => array('rule' => array('decimal', 2)));
It is obvious, what email does: it checks for a valid email address:
var $validate = array('email' => array('rule' => array('email')));
I am not sure whether money is fully implemented yet, at least I was not able to use this validation rule.
numeric is a simple wrapper for the PHP function is_numeric:
var $validate = array('age' => array('rule' => array('numeric')));
phone validates phone numbers. At the moment it supports only US phone numbers, if you want to validate other phone numbers you have to provide a regular expression.
var $validate = array('phone' => array('rule' => array('phone', null, 'us')));
postal is used to validate zip codes from the U.S., Canada, and the U.K. For other zip codes you have to provide a regular expression.
var $validate = array('zipcode' => array('rule' => array('postal', null, 'us')));
ssn validates social security numbers from the U.S., Denmark, and the Netherlands. For other social security numbers you have to provide a regular expression.
var $validate = array('ssn' => array('rule' => array('ssn', null, 'us')));
url is used to validate urls.
var $validate = array('website' => array('rule' => array('url')));
If you look at the validation class you will notice several other public methods. equalTo, file, ip, minLength, maxLength, multiple, and number are validation rules which are not implemented yet, so I don’t have described them. The userDefined method looks like it allows you to create custom validation methods, but up to now I couldn’t figure out how to use it…
Thanks to Nate for his initial explanations in the Google Groups.
Update 2007-01-06: minLength and maxLength have been implemented in changeset 4264. They can be used to validate the length of a string. If a string must consist of at least three characters you would do:
var $validate = array('username' => array('rule' => array('minLength', 3)));
And to validate that a string can consist of maximal 20 characters you do:
var $validate = array('username' => array('rule' => array('maxLength', 20)));
Update 2007-01-07: Also ip has been implemented, which is used to validate IP addresses.
var $validate = array('ip' => array('rule' => 'ip'));

You only need to wrap the rule in an array if it has parameters, so this is acceptable also:
var $validate = array(’website’ => array(’rule’ => ‘url’));
And less typing.
[...] More info at CakeBaker [...]
This is useful.
After browsing through the source yesterday I figured out how to use this, but messages that I had set in the model were not being outputted in the view.
I traced this back to two problems:
1. Model::invalidFields() had some bad logic in it. I had to replace
g^+-byjj\jYnߺwjɩ^^=ښg^+-V֭Wƥqk&Z'Z*'^^=ښ+buhyjji&j!^uZ~'t֦yn+ )jXjן]5buhgnwith
{a[zƫjjm++WWjn+ )jXjן]5buhgnۯlz'zhubjXjبyn}ƥqk&Z'Z*'^^=ښاbu^~'t֦z֭Ơynۯ蟊ƫjXj+^jjZkz kWj֟]5nۯa-{ږ'ZzWMjgjXj+,joverriding it in AppModel, of course.
2. Even if the field validated, the message was not being displayed in the view, so I overrode Helper::tagErrorMsg() in AppHelper to look like this:
~ܶ*'+2]mnޮ+պZ+6~'u+ ֠"'bun{))~Ȭjױ驷+^)߉]mz[^lz'kx+Z즸+nޖǛenۯI haven’t lodged a ticket about this, because the Validation class isn’t finished as it is.
Note: These are just quick fixes. They are just meant to get the system working like it should be.
@nate: I tried this approach, but I got an error, and so I thought my usage was wrong ;-) I reopened the ticket (see ticket #1850)
@Rob: Yes, the validation class is not finished yet. I am not sure if you will still use tagErrorMsg to display error messages in CakePHP 1.2 or if it will be done automagically by FormHelper::input(). We will see :)
to me “blank” can be very useful, imagine you have a form, and to prevent spambots you can define a field hidden with display:none. probably the spambot will fill it, so you can check for its validation if it’s not blank.
Maybe I’m missing something, but I don’t see how you would apply multiple rules to a field.
Also is there a way to call a custom function to validate a field?
@cakebaker: Helper::tagErrorMsg() is used by FormHelper::input(). I had to make the changes to have the validation message show at all.
Thanks this is very helpful.
userDefined looks to be still “work in progress” that would be one very cool feature to have. Do write about it if you figure it out otherwise
@kain: Yes, that is a possible use case. But I think something like “notBlank” would be more useful.
@MattC: This is something which is not possible yet, afaik. “userDefined” is probably thought to be used to call a custom function, but as I wrote in the article I couldn’t figure out how to use it. But as Tarique mentioned, it is possible that it isn’t finished.
@Rob: Yes, you are right.
@Tarique: Yes, that’s possible. If I know more I will write about it.
Any idea how to use a single validation rule on multiple variables? Like, if you need access to more than one variable for the validation.
@Cully: I am not quite sure if I understood you correctly. If you want to use a validation rule on multiple variables you would do something like:
var $validate = array('field1' => array('rule' => 'alphaNumeric'), 'field2' => array('rule' => 'alphaNumeric'));is it possible to have several validation rules for one field? Like to check username both for alphaNumeric and between or such. How $validate should look like?
I dunno about spambots but blank might be useful.
say you have a field called name, and you want the use either to enter an empty name or a string that is less than 17 characters. you set the first validation rule to be blank, if it passes that, it triggers maxLength. something like:
var $validate = array(
‘name’ => array(
array(’rule’ => ‘blank’),
array(’rule’ => array(’maxLength’, 17)))
);
but blank should test for ”, that is empty strings and not strings that have spaces in it
@acorus: I think it is not possible yet.
@CraZyLeGs: Well, you don’t need “blank” for the scenario you described, “maxLength” alone is enough.
@cakebaker: Why do not have $validate in such plain format:
$validate = array(’field’ => array(’validationmethod’, ‘param1′, ‘param2′))
or in case of multiple validations per one field:
$validate = array(’field’ => array(array(’validationmethod2′, ‘param1′, ‘param2′),
array(’validationmethod2′, ‘param1′, ‘param2′)
))
so, here we do not need ‘rule’ key at all (and what it’s aim now?) and less typing.
sorry, first validationmethod should be validationmethod1 :)
cakebaker: ok maybe maxLength isn’t the right example, I’ll rephrase, you would want to validate either an empty string, or a fixed length string, so 0 OR 17. Anyway I hope this validation thingy gets a bit more advanced it’s really an archaïc need. done right is a must for a framework.
@acorus: I think the reason for the more complex structure is that more functionality is planned, e.g. defining the error message. But we will see.
@CraZyLeGs: Ok, that makes sense. I am not sure if that will be possible, you probably would have to define your own rule. I agree with you that the validation is a very important part of the framework.
Uhm, the blank thing is really confusing, it actually returns true only if the field is left blank…. not much useful in most cases.
Ok, and I finally got the userDefined thing works, if you want to use it, you have to overwrite it (be warned that maybe it’s just me who don’t know the right way to use it):
In your app_model.php pastes this (inside the class, of course)
function userDefined($check, $object, $method, $args = null) {
return call_user_func_array(array(&$object, $method), array ($check,$args));
}
Then say I want to validate that the uploaded field is valid, in my model I have:
var $validate = array(’picture’ => array(’rule’ => array(’userDefined’, ‘Entry’, ‘isImage’)))
Then of course I need a function called isImage in Entry model or app_model if I want to use it in other models.
Hope this helps you cause I have been pulling all my hairs just to figure out why it didn’t work for me.
Vu Nguyen.
@yellow: Hm, I am not sure if that is the correct way, at least it doesn’t work here :| Anyway, thanks for sharing it!
Weird, it works on my end.
Can you tell me exactly how it doesn’t work cakebaker?(any error? etc)
VN
@yellow: My bad, I copied the code from your comment but it contains wrong “‘” characters (it seems they are automatically replaced by wordpress) and my test case didn’t show any warnings. Today I tested it manually and I saw the warnings.
So your approach works fine ;-)
thank you nate, this was thoroughly helpful
Can you call the the validation function in your controller, I have a method that is saving things to two different models and i just noticed the first one is getting done even if the second is not valid.
Usefull article, thanks!
@letimati: Yes, you can validate your data in your controller with something like
HTH
this does not seem to work in 1.2.x.x
After having a look into it here is what i found.
calling $this->yourmodel->validates() just calls the function with an empty array because the $data is not set. when you call if($this->yourModel->save($this->data))
the data gets set and then the validates() function is called with data.
So i tried just passing the data with the validates function in my controller
$this->yourmodel->validates($this->data)
however you get this warning
(Model::validates) Parameter usage is deprecated, set the $data property instead
Warning (512): [CORE/cake/libs/model/model.php, line 1647]
I could just take this warning out but there should be a way to validate your data yourself.
thanks for the reply by the way.
@letimati: As I wrote in my previous comment, you have to use the “create” function first to set the data. Probably my example was not clear, so here an improved version:
if ($this->YourModel->create($this->data) && $this->YourModel->validates()) { // validation ok } else { // validation not ok }$validate =
array
(
’picture’ =>
array
(
‘rule’ => array(’between’, ‘6′, ‘60′),
‘message’ => ‘Client Name must 6-60′
)
Hay thanks that was my fault i did try the create in there as well but i was not passing it anything!
Sorry for not reading it properly.
great site though i have found more useful things off this than the bakery
if i have something like that in the model,
var $validate = array(
‘username’ => array(
‘required’ => VALID_NOT_EMPTY,
‘length’ => array(’rule’ => array(’between’,3,10))
);
and in my cake template,
input(’User.username’, array(’error’ => array(’required’ => ‘Username is required’, ‘length’ => ‘Username too short’),
’size’ => ‘20′, ‘maxlength’ => ‘32′, ‘label’ => false )) ?>
whenever there is an error, no matter which one, the error message will be “Array”, seems like the formhelper isnt able to pick up which error to display but just display the error array. anyone has an idea what is wrong ?
got it fixed by getting the latest build.
@silk: Hm, what do you try to say?
@letimati: No problem, I am happy to read that this blog is useful for you, thanks :)
@yangz: I am glad you could fix that issue in the meantime.
I can’t seem to get the error output to the view working. I’m using cake_1.2.0.5146alpha at this moment. My Model:
class User extends AppModel
{
var $name = ‘User’;
var $validate = array(
‘uname’ => array(
‘required’ => VALID_NOT_EMPTY,
‘length’ => array(
‘rule’ => array(’between’,3,10)
)
)
);
My Controller:
if(!empty($this->data)){
if($this->User->create($this->data) && $this->User->validates()) {
print “DATA OK”;
} else {
print “DATA NOT OK”;
}
}
My view:
tagErrorMsg(’User/uname’, ‘not goood’); ?>
input(’User/uname’, array(’error’ => array(’required’ => ‘Username is required’, ‘length’ => ‘Username too short’), ’size’ => 20, ‘class’ => ‘field’)); ?>
When the page is first opened the output for $html->input is:
Notice (8): Array to string conversion [CORE/cake/libs/view/helper.php, line 296]
The html code is:
When the form is submitted and leaving the username field empty, no error information is outputted, only ‘DATA NOT OK’. When something valid is filled in the username field the output is: ‘DATA OK’
Solved my problem… The Controller should load the FormHelper and then the view should use the form helper instead of the html helper:
$form->input(); etc.
Thanks anyway :)
(p.s. your wordpress comment-system contains a fault. All posts are dated ‘2007-01-03, 18:04′, the exact same date as the article itself!)
@Ron: Good to hear you could fix your problem in the meantime :)
Yes, I am aware that there is a problem with the comment system, but up to now I don’t know what causes that effect…
Is it possible to compare two fields of the models ? Like two dates (date_start and date_end). if date_start array( ‘rule’ => array(’comparison’, ‘>’, …. )));
Someone has an idea ?
Thanks
Sorry my last post was cut.
Is it possible to compare two fields of the models ? Like two dates (date_start and date_end). if date_start is less than date_end the form is valid, else it is not valid. I guess i should use
Someone has an idea ?
Thanks
@titang: I don’t know whether it is possible to use “comparison” in that way. I usually do such validations in the beforeValidate() method of my models.
@all
Once thing i have find out in order to display error message in for your custom form elements (stuff that not created by formHelper )
$html->tagErrorMsg() is depreciated
Use
$form->error() instead,
example:
// for user id cannot be found
$form->error(’User.id’, ‘User id cannot be found’);
For cake 1.2
simple & generic solution
to check for unique field name, this works really well,
truly DRY
/* Your validate data array as usual */
var $validate = array(
‘user_id’ => VALID_NOT_EMPTY,
‘name’ => array(
‘required’ => VALID_NOT_EMPTY,
‘unique’ => array(’rule’=>array(’isUnique’,'name’),’message’ => ‘name already exist’)
),
‘field2′ => array(
‘unique’ => array(’rule=>array(’isUnique’, ‘field2′), ‘message’ => ‘Field 2 already exist’)
)
);
// Put a generic method in AppModel
class AppModel extends Model{
function isUnique($data, $name){
return !$this->hasAny($this->name.”.$name=\”".$data.’”‘);
}
}
?>
Updated
fix bug for “edit” action,
if you editing the current object, without changing the db name
//
function isUnique($data, $name){
$found = $this->find($this->name.”.$name=\”".$data.’”‘);
$same = isset($this->id) && $found[$this->name]['id'] == $this->id;
return !$found || $found && $same;
}
@speedmax: Thanks for your additions! I would choose a different function name though as there already exists a “isUnique” function in the model class.
@cakebaker: Thanks. I found out the naming clash later that day, probably rename to “validateUnique” or even “unqiue”
Model::isUnqiue() does similar things but more for checking uniqueness against a specific field
whereas the function i proposed is focus on validation, for crud action. there is a bit of logic redundant.
it could be simplified, but for now it works. :)
/* Your validate data array as usual */
var $validate = array(
‘user_id’ => VALID_NOT_EMPTY,
‘name’ => array(
‘required’ => VALID_NOT_EMPTY,
‘unique’ => array(’rule’=>array(’unique’,’name’),’message’ => ‘name already exist’)
),
‘field2′ => array(
‘unique’ => array(’rule=>array(’unique’, ‘field2′), ‘message’ => ‘Field 2 already exist’)
)
);
// Put a generic method in AppModel
class AppModel extends Model{
function unique($data, $name){
$found = $this->find($this->name.”.$name=\””.$data.’”‘);
$same = isset($this->id) && $found[$this->name][’id’] == $this->id;
return !$found || $found && $same;
}
}
@speedmax: Thanks for the update :)
The unique function really needs to have recursive set to -1. Otherwise you are joining on all the tables just to check if one field in one table is unique. Without the recursive = -1 you the function will also fail to find duplicate data if in one of the joined tables the current model does not have a related row yet.
the function should be:
function unique($data, $name){
$this->recursive = -1;
$found = $this->find($this->name.”.$name=\”".$data.’”‘);
$same = isset($this->id) && $found[$this->name]['id'] == $this->id;
return !$found || $found && $same;
}
Hi guys and thanks for that information.
Anyway, I don’t fully understand the notation:
$found = $this->find($this->name.”.$name=\””.$data.’”‘);
and do not manage to make it work. Sorry if it is obvious but I’m new to cakePHP so….
Thanks
@martin: Well, you can translate the statement to:
$found = $this->find('ModelName.fieldName = "someValue"');What happens is a simple string concatenation.
Hope that helps :)
[...] Validation with CakePHP 1.2 by Cakebaker again. [...]
[...] http://bakery.cakephp.org/articles/view/multiple-rules-of-validation-per-field-in-cakephp-1-2 http://cakebaker.42dh.com/2007/01/03/validation-with-cakephp-12/ Na ir daugybę klausimų/atsakymų CakePHP Google groups: [...]
Nice article ! Thank you for posting it.
Do you know how to disable from a controller the validation on a certain field ?
For example, I don’t want the e-mail address to be checked, but all the rest of the validations should occure when using validates() ?
Thanks !
@Madjik: Thanks for your comment!
I would simply unset the corresponding validation rules:
HTH
[...] order of priority, it can be a custom model method (defined in AppModel or TestModel), a Validation method or a custom [...]
[...] code isn’t a big concern for me. The code was inspired by the comments between speedmax and cakebaker on his blog. // YourModel.php var $validate = array( // validate our username and email ‘username’ [...]
To compare two fields of the form you could try something like this:
var $validate = array(
‘password’ =>…,
‘password2′ => array(
‘valid’ => array(’rule’ => array(’compareData’,'password’),
‘message’ => ‘** error **’)
)
and in app_model:
function compareData ($data, $field) {
return ($data == $this->data[$this->name][$field]);
}
you also could add another parameter with the operation to perform (’==’, ‘>=’, …).
@diyo: Thanks for your example! Only a detail, but I would add the compareData() function only then to the AppModel when it is really used by different models, else I would simply add it to the respective model.
@diyo : nice one . i have similar methods but more generic confirm methods.
function confirm () {}
automatically checking data['password_confirmation'] and data['password'], and it can be used for anything. data['xx'] will need to be confirm with data['xx_confirmation']..
If compareData() doesnt rely on any other methods in a specific model, I would place it in app_model in any case. I think that if a method -can potentially- be used in a broader context it should be available in such a way, because at some point you might need in other models, even if you think that’s not the case at time of writing the function. Afterall, you can tell by its name that afunction like compareData is not related to a specific model.
Likewise (but not quite the same), that is why I consider it a best practice to make seperate method for a custom query in a model. That way, it is accessible for other methods, that might need it later on.
@Tim: Thanks for your comment.
I disagree with you. I think you should put stuff only then into the AppModel when it is really necessary, following the YAGNI (= You Ain’t Gonna Need It) principle.
On the other hand I agree with you on the topic of creating a separate method for a custom query in the model.
@cakebaker: Did not know YAGNI until now. :) However, a method like compareData is “likely” to be used elsewhere so i think it depends on the situation. Keep in mind that Cake, or any other framework loads a lot of convenient functions in memory that are possibly never used.
@everyone:
Ok another thing that was asked here, howto use multiple rules for a single field:
var $validate = array(
‘id’ => VALID_NOT_EMPTY,
‘username’ => array(
array(’rule’ => VALID_EMAIL,’message’ => ‘invalid email’),
array(’rule’ => ‘uniqueUsername’,'message’ => ‘username allready exists!’)
),
‘password’ => VALID_NOT_EMPTY,
‘activated’ => VALID_NOT_EMPTY,
);
maybe not a good example but you get the idea. works in 1.2.0.5427alpha. keep in mind that ALL rules will be evaluated and that only the message of the last invalid rule will be shown in the view.
@Tim: Yes, that’s true that Cake loads a lot of stuff you probably never use, but that doesn’t mean you should do the same ;-)
Thanks for your example!
[...] Validación con CakePHP 1.2 por Cakebaker. [...]
What is the order of appliance in validation array ? Which rule is applied first ?
In my situation, i have two validation rules, one is for length, and the second is for checking alphanumeric. If the length validation is the last element in validation array, then the alphanumeric validation does not work.
e.g :
‘username’ => array(’alfanumerik’ => array(’alphaNumeric’), ‘required’ => VALID_NOT_EMPTY, ‘length’ => array(’between’, 3, 10))
I discovered (i think) that the last element is executed first. If i change the order, put alpha thing last, and length thing first, then everything is fine.
@serkan: Thanks for your comment!
I would have guessed that the rules are applied in the order they are defined, but it seems it is the other way around.
I think the order of the rules shouldn’t matter, so what you described could be a bug.
[...] 首先有两篇文章可以看看《Simple Form Authentication in 1.2.x.x》、《Validation with CakePHP 1.2》这两篇文章都是很好的入门读物,甚至包括回复部分也都值得看看。 [...]
Thanks for this article, it has been VERY helpful in learning about validation in 1.2. Beyond this, most of what I’ve been able to learn has been from analyzing the code of the framework itself, which is tedious and cumbersome.
@Matt: I am glad it is useful for you. I agree with you that it is rather cumbersome if you have to read the source of the framework to learn how it should be used. And sometimes even that doesn’t help…
serkan, i always thought all rules for a single field are processed in any case but if both rules fail (if you have two of them that is), only the message of the last rule will be shown…but as far as i know, if at least one of the rules fails, your data should be saved…at least thats what i thought, maybe i should doublecheck.
will be shown, as in, only the errormessage of the last rule will be shown in the view.
anyway,it’s a way not perfect.
@soxy: What do you refer to with “it’s a way not perfect”?
[...] More about Cake validations are here: http://cakebaker.42dh.com/2007/01/03/validation-with-cakephp-12/ [...]
I am a bit confused by all the different formats and variations people gave for using the new validations. Any chance I can get a clear and complete example on how to set validations for 2 fields, say an email and password, with error messages?
From my understanding, the correct format is:
var $validate = array(
‘email’ => array(
array(’rule’ => array(’email’), ‘message’ => ‘invalid email’)
),
‘password’ => array(
array(’rule’ => array(’alphaNumeric’), ‘message’ => ‘invalid characters’),
array(’rule’ => array(’between’, 6, 10), ‘message’ => ‘password has to be 6 to 10 characters long’)
),
);
but I can’t seem to get it work (show a message, or halt the execution of the action) in my tests.
@senseBOP: Yes, that’s the correct format. Here an example action and view, which work fine with your validation array:
function add() { if ($this->data) { if ($this->User->save($this->data)) { $this->redirect('/users'); } } }echo $form->create('User'); echo $form->input('email'); echo $form->input('password'); echo $form->submit('Add'); echo $form->end();Hope that helps!
[...] Валидация input полей в формах [...]
Any news about showing the error messages ?
Validations work fine but no way the custom messages to appear!
@Tiago: It should work fine. Did you have a look at the example above (comment from senseBOP and my answer)?
Hope that helps!
I got it!
My action edit’s logic was exiting when an error occurs, so the page wasn’t being rendered after that!
And with $form->error() in the view it works fine.
Something I notice with $form->error:
if it has an error message, $form->error(’User.id’, ‘User id cannot be found’), this message will be shown on whatever error that occurs.
if it hasn’t a message, $form->error(’User.id’), the message especified in the model will be shown.
Thanks for the reply!
Is there a way to do an “or” on validation rules?
ie
blank or range(2-10)
@tiago: I am glad you could it make work!
@Bryn: In your specific case you could set allowEmpty to true:
var $validate = array('field' => array('rule' => array('between', 2, 10), 'allowEmpty' => true));For more complex conditions you would have to use something like the ConditionalValidation behavior (http://bakery.cakephp.org/articles/view/conditinalvalidation-behavior).
[...] – Multiple rules of validation per field in CakePHP 1.2 cakebaker.42dh.com – Validation with CakePHP 1.2 tempdocs.cakephp.org – Data [...]
[...] Mejoras en la validación: se agregan reglas para validación automática como alfanumérica, email (brillaba por su ausencia), url (idem), y en definitiva se provee de métodos de validación mucho más completos (por ejemplo la validación “custom” que nos permite usar expresiones regulares. La lista es gigante, y puede encontrarse aqui. [...]
in the validation array i have something like ‘email_like’ => array(’rule’=>’email’,'message’ => __(’Email expected’,true)) but it gives me error, if i dont use __(”) function everything is ok. Enyone can tell me how can i use i18n for validation error strings?
@KireZ: See the following thread in the group: http://groups.google.com/group/cake-php/browse_thread/thread/6ac5b6520c7e39df/2d8032f94ef1aa33
Hope that helps.
Hi, I was hoping you could explain how you extracted your examples from the API. I’m still new to cakephp and OOP, but I can’t for the life of me understand how you got your examples from the validation class reference. Any pointers in the right direction would be invaluable to me. THANK YOU.
@Erik: Hm, good question. I think one of the devs explained it and/or posted an example to the cakebin, and from there I could derive the other examples. From the API alone I wouldn’t have been able to figure out how to use the validation stuff…
Don’t know if that helps you much :|
[...] en la propia API de CakePHP 1.2, aunque una información menos densa la encontramos en la Bakery, interesante sobre todo por los comentarios finales de la gente, que aportan muchas [...]
Cool article!
I got a question – cake automatically repopulates the form with data if validation fails. Is there a way to disable the automatic repopulation for some specific fields? i.e. I have a “password” field, which has a validation rule of (minLength,5) – if the validation fails the field gets repopulated, and i want it to show as empty. Is there a way to do it other then manually settin ‘value’ = ”??
Thanks for your help
@Hubert: I think you have to manually remove the data from the array with something like:
if (isset($this->User->validationErrors['password'])) { unset($this->data['User']['password']); }Hope that helps!
How can I validate a field as valid email adrress and unique at the same time? I try this, but it fails:
var $validate = array(
‘email’ => array(
‘unique’ => array(’rule’ => array(’unique’, ‘email’), ‘required’ => true, ‘message’ => ‘E-Mail is already in use’), ‘email’ => array(’rule’ => ‘email’, ‘required’ => true, ‘message’ => ‘Invalid E-Mail’)
);
class AppModel extends Model
{
function unique($data, $name)
{
$this->recursive = -1;
$found = $this->find($this->name.”.$name=\”".$data.’”‘);
$same = isset($this->id) && $found[$this->name]['id'] == $this->id;
return !$found || $found && $same;
}
}
@Dimitar: I’m not sure what exactly you mean with “it fails”, but from looking at your example it seems to me that you use $data incorrectly. It is an array (containing a field name/value pair). So, to get the value you have to use something like:
Hope that helps!
thanks cakebaker, but allowEmpty still sets the css class of the input to required. Is there anyway to get around that?
@Bryn: Which Cake version do you use? At least with the quick test I did with revision 7334 I couldn’t reproduce it, there was no “required” class set. And according to ticket 3869 this issue should be fixed. If you can still reproduce it with a recent Cake version, please open a ticket on trac.
Hope that helps!
Another useful post Daniel.
If anyone wants to implement a ’strong’ password validation like those seen in most sites, use the custom validation method with a regular expression similar to the one below;
'/(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/'That requires a minimum of 8 characters
Atleast 1 Upper case
“” 1 lower case
“” 1 digit OR 1 special character
@Edward: Thanks for this regular expression!
@KireZ:
Hi,
In Php, you can’t use a function outside a class method. So the __(”) function in var $validate will cause an error.
You have to move $validate in a constructor.
See example below:
Don’t forget to add :
parent::__construct();@Jay: Thanks for your additional explanations!
[...] validation class is pretty powerful, however there may be a time when you require a validation method that hasn’t been defined and therefore requires yourself to develop. This is where custom [...]
‘url’ => array(
‘rule’ => ‘url’,
‘required’ => false,
‘allowEmpty’ => true,
‘message’ => ‘Invalid URL format.’
)
this validation accepts url like “test.com” ?
this is not a proper url format…….
@Jaydeep: Yes, this validation rule accepts “urls” like “test.com” which is, as you say, not correct according to RFC 1738. So I reopened a ticket for this issue which was closed a while ago as “invalid”. Maybe it will get fixed…
the idea of having $validate set on __construct is certainly a bad and by any means a good design. Validation rules are part of the signature, specification and concept of the Model, and as such should be signed on it’s declaration.
There are so many other means to achieve L10n on error messages, and probably the best is direct in the view layer:
1 – you’ll won’t suffer the overhead of having localised messages you won’t use;
2 – there are absolute no usage for translated messages being set on the “runtime environment” (if you test errors by it’s message, know that it’s totally bad design: errors should be tested by code) so they should only be translated where they will really be used.
@Rafael: Setting $validate in the constructor is not worse than setting $validate in the traditional way. It is just a different way to accomplish the same.
And regarding L10n of error messages, I think it depends on your point of view whether you localize them in the model or in the view. Doing it in the model has the advantage that it is DRY (don’t repeat yourself).
I think there is a bug in maxLength validation. (??)
I must set maxLength to 6
in order to effectively limit to 4 characters. There’s an extra 2 unaccounted for characters.
For example try this validation code on field “Name:”
var $validate = array(
‘name’ => array(
‘alphaNumeric’ => array(
‘rule’ => ‘alphaNumeric’,
‘allowEmpty’ => false,
‘message’ => ‘no crazy characters allowed’
),
‘maxLength’ => array(
‘rule’=>array(’maxLength’,6),
‘allowEmpty’ => false,
‘message’ => ‘no more than 4 characters allowed’
)
)
);
Starting with a submission of 123456™, you get the error “no more than 4 characters allowed” and don’t get the error “no crazy characters allowed” until you cut the field submission down to 123™.
Any thoughts on why this is?
more about the above
I tested “maxLengh” alone, with no other conditions, and it works fine.
But when coupled with a second condition (alphaNumeric) as described above, it is again off by two characters.
My only theory is that in the encoding and form submission process, non-alphanumeric characters (like ™ and ∞ and ¶) get converted to multiple characters.
Reversing the order of the conditions, so that it checks for alphaNumeric first makes this a non-issue. Hope this is helpful….
@Matthew: Yes, it is because those characters are multibyte characters and Cake uses the strlen() function in the Validation::maxLength() method. And strlen() doesn’t work correctly with multibyte characters (you would have to use mb_strlen()). For example, if you use strlen(’™’) it returns 3…
What about conditional validation?
assume $this->MyModel['flag'] and $this->MyModel['field']
I want to validate ‘field’ ONLY if ‘flag# is set ?
any idea?
@nowasabi: You have to write a custom validation method. Something like
Hope that helps!
Thanks that helped a lot.
Please let me ask another question:
I stumpled about a “simple” task :
echo $form->input(’appointment’,array( ‘dateFormat’ => ‘DMY’,
’separator’=>”, ’showEmpty’=> true);
This does not work. How do I get an empty date fieldset?
@nowasabi: Well, you are using a non-existent option, replace “showEmpty” with “empty”, and it should work :)
Hi, I’m just a beginner like me to know how to apply the label appearance, ie the appearance of the error message:
echo $ form-> error ( ‘User.state’, array (’?'));
Thank you very much
@yoxs: Hm, I don’t understand what you try to accomplish :| Can you elaborate a bit more on what you try to do?
about ‘blank’ rule:
problem: i want validate field ‘id’ .
use case
1. adding rows to table (then ‘id’ is left blank);
2. modifing rows in table (then ‘id’ should be correct one)
my rule:
i wonder if it is right build of the rule (order of the rules and how cake behave analizing them), but
how to validate ‘id’ field without ‘blank’ rule?
regards,
m
@m: Hm, I’m not sure I understand what you try to accomplish, but maybe the “on” option is what you are looking for. You can set it to either “create” or “update”, which then determines when the respective rule is applied. See also http://book.cakephp.org/view/127/One-Rule-Per-Field.
Hope that helps!
@cakebaker: it seems to me, that i’ve missed sth. i didn’t know about ‘on’. Now my rules (not only checking ‘id’ but also ‘username’, ‘pass’ …) will be much clearer.
But now i wonder if i realy need to validate field ‘id’, or it’s just my paranoic atitude.
Thanks a lot,
m
@m: Personally, I don’t validate the “id” field because I usually use the auto-increment feature of MySQL. However, this means I have to ensure that an “id” provided by the user is ignored when creating a new record. For this purpose the $fieldList param of Model::save() can be used.
Hope that helps!
Usefull, thank you!
@Atea: You are welcome!
I have the problem with my validation, my form will never been validate.
I am a beginner, can u help u to solve my problem?
This is my View:
It is really urgent! Hope u can reply ASAP!
thanks for helping!
@von: Hm, one possible issue could be the “required” option, because it should be a boolean value (see http://book.cakephp.org/view/127/One-Rule-Per-Field#required-129), though I’m not sure whether this is the reason it doesn’t work.
Did you have a look at what $this->data contains?
Hope this helps!
I have the same problem as senseBOP and tiago. I am having a similar view page and a controller as mentioned by you. Also I tried including the $form->error message in the view as said by tiago,Yet I do not get error msgs when I give invalid inputs. It just goes to the next page,but the entry does not get saved in the database.
@Angeline: Hm, do you do a redirect when the validation fails? If you do, then remove the redirect, and try it again.
Hope that helps!
Earlier I had a redirect when the validation failed. But now I have changed the code as given below. Yet i dont get the error messages.
Only when the login is successful,I do a redirect to the homepage. Is there any method to render the next page without using a redirect. I also used $this->render(),but it doesn’t work. Please help me.
@Angeline: Hm, somehow I don’t understand what the problem is. If you post data to the register() action, what happens then? Do you get any errors? And what is displayed?
And instead of using the flash() method (because it makes a redirect) I would use $this->Session->setFlash(’your message’) in your controller, and echo $session->flash() in your view to show the message.
Hope that helps!