CakePHP Tips – Winter 2012

Some more tips I gathered the last couple of weeks and want to share with the (Cake/PHP)world 🙂

Jquery and CakePHP FormHelper::radio()

Usually you would use

var value = $('input[name=fieldName]:checked').val();

But since CakePHP uses name="data[ModelName][field_name]" generating the form fields you cannot just use input[name=data[ModelName][field_name]]. Two brackets inside each other rare not allowed.
So you need to do it this way:

var value = $('input[name=\'data[Default][status]\']:checked').val();

The escaped field name will make it work again.

How to dynamically overwrite the error message

The most important fact for me is: This was the reason I finally figured out how to override the error message from within a custom validation method.
I played around with it and with some help from stackoverflow/irc I solved the problem I had not been able to solve so far. So with that I want to start.

Imagine a custom rule that calls a webservice or another class which then could throw an exeception. We want to catch the message of it and display it instead of the default message "Something went wrong" 🙂
It is actually pretty easy, just do not return false but the error string itself:

    public $validate = array(
        'url' => array(
            'validateUrl' => array(
                'rule' => array('validateUrl'),
                'message' => 'valErrDefaultError',
            ),
        ),
    );

    public function validateUrl($data) {
        $content = array_shift($data);
        try {
 			...
 		} catch (Exception $e) {
            //crazy stuff which is working but NOT RECOMMENDED in this case:
 			//$this->validator()->getField('url')->getRule('validateAvailability')->message
 			//return false;
 			
            //just return the error message you want to replace the default one with
 			return $e->getMessage();
        }
        //no exception thrown - seems to be fine then
        return true;

PS: The commented out code SHOULD NOT be used, but would also work. Those are from my trial and error runs figuring it out. Using the new validator object you can access the properties prior to their usage.

But the simple and correct way here is just to return the error string.
So in our case the form field will have the error message from the exception now.

PS: Returning boolean false will make the original error message defined in your validation array to be displayed, of course.

The book already has quite a thorough documentation on how to Dynamically-change-validation-rules.
Using the validator object basically saves you the trouble working with the $validate array directly.

Avoid "pass by reference" outside of method scopes

<?php
$spell = array("double", "toil", "trouble", "cauldron", "bubble");
foreach ($spell as &$word) {
    $word = ucfirst($word);
}
foreach ($spell as $word) {
    echo $word . "\n";
}

Results in

Double
Toil
Trouble
Cauldron
Cauldron

An issue well known to many (here or here).
So avoid it in view templates where you might re-use the variable somewhere later in the code or always remember to unset it after the foreach loop etc.
The advantage of using small methods in helpers, components, etc is that the scope of the variable is only inside this method and can not affect anything else anywhere.

And in general, trying to avoid the pass by reference is often the best approach. At least where memory is not an issue.

5.00 avg. rating (93% score) - 1 vote

4 Comments

  1. In the first example you can also use the other kind of quotes, eg.: ‘input[name="data[Default][status]"]:checked’

  2. Great tips. For the first example I usually target my form fields using their id to avoid this. However, knowing the proper way to target them by name is very useful. I am sure I’ll be fixing some code someone else wrote and I can now easily identify this problem.

  3. For radio you cannot the ID – as its a unique attribute whereas radios by definition consist of more than just a single element.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.