Ajax name check

When a user signs up to your website, trying to find a username that is not already in use can be a real pain and could cause them not to sign up if they are repeatedly presented with an error. To solve this you can use a simple bit of JavaScript to check if their chosen username is available before submitting their registration.

Controller

The first thing to do is set up the Users controller in cakePHP. Add a new function called ‘check’, which checks if the username is already in the database. The most that should be returned is 1 if the username is in use or 0 (zero) if not.

<?php function check($username = null){
    $this->autoRender = false;
    if(!$username){
        return 'Error checking username';
    }else{
        if($this->User->find('count',array('conditions'=>array('User.username LIKE'=>$username)))){
            return '{"status":0,"message":"'.__('Sorry the username ',true).$username.__(' is already in use',true).'"}';
        }else{
            return '{"status":1,"message":"'.$username.__(' is available',true).'"}';
        }
    }
 } ?>

The first thing to notice is the $username variable, which means it requires a GET request and we don’t want php to throw an error if it was not set so we set it to ‘null’, that way we can handle the error ourselves. We don’t need a view rendered for this action because we just need the strings returned, to prevent cake looking for a view file we set autoRender to false. Next we deal with what happens in the unlikely event of no username being sent, just return an error message. Now we need to return a different message depending on whether a record is found or not. This function checks the username field in the Users table, so if you have a different table or field name alter the code accordingly.

View

This is a basic user registration view.

<div class="users form">
<?php e($this->Form->create('User')); ?>
<fieldset>
<legend>< ?php __('Add User') ?></legend>
<?php
    e($this->Form->input('User.name'));
    e($this->Form->input('User.username',array(
        'after'=>'<button id="chkBtn">Check Username</button>',
        'div'=>array('id'=>'usernameDiv')
    )));
    e($this->Form->input('User.email'));
    e($this->Form->input('User.new_password', array('type'=>'password')));
    e($this->Form->input('User.confirm_password', array('type'=>'password')));
?></fieldset>
<?php e($this->Form->end('Submit')); ?></div>
<?php e($javascript->includeScript('check_user')); ?>

Javascript

If you have not added the YUI files to the layout file just add this the view file that you want the user name check on. This will then be added to the $scripts_for_layout in your layout;

echo $this->Html->script('http://yui.yahooapis.com/3.1.0/build/yui/yui-min.js',array('inline'=>false));

Next create a file called “check_user.js” in the “/webroot/js” directory and add the following, this will be included in the view by the last line of the view file.

YUI().use("node","json","io-base",function(Y){
    var d = Y.one('#usrNmStus');
    var usr = Y.one('#UserUsername');
    var gH = {
            write: function(str) {
                             d.set('innerHTML',str);
            },
            start: function() {
                             this.write("");
            },
            success: function(id,o) {
                try {
                    var data = Y.JSON.parse(o.responseText);
                }
                catch (e) {
                    this.write("Invalid data");
                }
                if(data.status == 1){
                    d.removeClass('error');
                    d.addClass('success');
                }else if(data.status == 0){
                    d.removeClass('success');
                    d.addClass('error');
                }
                Y.log(o);
               this.write(data.message);
            },
            failure: function() {
                               this.write("Error");
            }
    }
    Y.on('io:start', gH.start, gH);
    Y.on('io:success', gH.success, gH);
    Y.on('io:failure', gH.failure, gH);

    function call(e, b){
        e.preventDefault();
        user = usr.get('value');
        Y.log(user);
        Y.log(e);
        Y.io('/users/check/' + user);
    }
    Y.on('click', call, "#chkBtn", this, false);
});

When a user clicks the button, the message will be displayed below the username input field. If the username is available the div will have the class of “success” added to it, if not the class of “error” will be added. You should add appropriate rules to your css file. Bellow is an example.


/* Message Styles */

.error, .notice, .success {padding:.8em;margin-bottom:1em;border:2px solid #ddd;}

.error {background:#FBE3E4;color:#8a1f11;border-color:#FBC2C4;}

.notice {background:#FFF6BF;color:#514721;border-color:#FFD324;}

.success {background:#E6EFC2;color:#264409;border-color:#C6D880;}

.error a {color:#8a1f11;}

.notice a {color:#514721;}

.success a {color:#264409;}

Comments and retweets are welcomed and encouraged :).

6 thoughts on “Ajax name check

  • Pingback: CakePHP : signets remarquables du 06/08/2010 au 09/08/2010 | Cherry on the...

  • August 12, 2010 at 12:12 pm
    Permalink

    Can you explain what the purporse of the 0_Sorry and 1_Success part of the returned string are? I’ve always wondered how to set an error response code when returning something to an ajax request instead of having to put logic and to check what I’ve returned.

    Reply
    • August 12, 2010 at 5:47 pm
      Permalink

      Sorry, that bit of code was from one of my older files, I have updated it above. Basically it now returns a JSON formatted array which is then used by the javascript to display the message and change the class of the div with the id of “usrNmStus”, according to the status.

      Reply
  • December 7, 2010 at 3:43 pm
    Permalink

    What about modifying the code to suggest alternate user names? You could base this off of other info supplied by the user (i.e. “Full Name”). If you have a few different ways of generating user names and then be sure to call back to the check() function for each one. You this this kind of functionality on sites which are very busy, like yahoo.co.uk

    Reply
  • May 3, 2011 at 6:15 pm
    Permalink

    thanks for posting the article

    Reply
  • July 13, 2011 at 4:54 am
    Permalink

    What version of CakePHP is this aimed at? I have a feeling it’s 1.2. Any chance of an update for 1.3?

    Thanks

    Reply

Leave a Reply

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