views:

203

answers:

3

When I save the information from a registration form I have some validation rules on the username and email fields (I've pasted the rules below). Validation is called automatically with the saveAll() function.

The problem is that the isUnique rule on the username field doesn't work at all (doesn't return any error). The other rules for this field work just fine, and the unique validation for the email field also works. I can't seem to figure out why this is happening, when the two rules are basically the same.

var $validate = array(

    'username' => array(

        'isUnique' => array (

            'rule' => 'isUnique',

            'message' => 'This username already exists.'),

        'custom' => array (

            'rule' => array('custom', '/^[A-Za-z0-9,\.-_]*$/i'), 

            'message' => 'The username can only contain letters, numbers, _, - and .'),

        'minLength' => array(

            'rule' => VALID_NOT_EMPTY,

            'message' => 'You must fill in the username.')          
    ),

    'email' => array(

        'isUnique' => array (

            'rule' => 'isUnique',

            'message' => 'This email address already exists in our database.'),

        'valid' => array (

            'rule' => array('email', false),

            'message' => 'Invalid email.'),

        'minLength' => array(

            'rule' => VALID_NOT_EMPTY,

             'message' => 'You must fill in the email address.')

    )

);
A: 

Looked at my user model, and it looks like this:

var $validate = array(
    'username' => array(
        'inUse' => array (
            'rule' => array('isUnique', 'username')
        )
    )
)
Oscar
It still doesn't work. I'm pretty sure the syntax is correct, since it works for the email field (and it is also the way it is presented on book.cakephp.org). Right now I'm trying to find other causes that would prevent that rule from working for one field, but not for the other.
A. M.
A: 

I still can't find what the problem is, so as a temporary solution I've written a custom rule. In case somebody else needs this:

var $validate = array(
    'username' => array(
        'isUnique' => array (
            'rule' => array('checkUniqueUser'),
            'message' => 'This username already exists.'
        )
    )
)

function checkUniqueUser() {
    return ($this->find('count', array('conditions' => array('User.username' => $this->data['User']['username']))) == 0);
}
A. M.
+1  A: 

The "isUnique" rule looks for repeating values in other rows. Which will create a problem if the "isUnique" test is also the primary key. So, based on your rules/model above, if you look at the SQL dump when the rule is run, you will likely see something like

SELECT COUNT(*) FROM users WHERE username = 'x' AND username != 'x'

This obviously returns 0 or "unique" in the test. Fix would be to set the primary key equal to something other than the field you are testing the rule on. When you do that, the SQL dump should show something like

SELECT COUNT(*) FROM users WHERE username = 'x' AND key != 'y'

This will return the >0 when the field is not unique and the desired functionality will be restored.

Rent Jungle
You're right, this solves the problem. Thank you.
A. M.