CakePHP 2 “remember me” feature

So I am going to show how to implement a “remember me” feature in CakePHP 2 while utilizing Cake’s Auth.

I assume that you already have a working installation of CakePHP 2 and that the controller which you are using for authentication is called: User. Also, that your username and password fields in the ‘users’ table are called respectively ‘username’ and ‘password’( this should be the case if you want Auth to handle things automatically for you ). If you don’t have Auth configured and working you can go here and follow the instructions there.

So firstly, add the following code to your login form view. This is just using CakePHP form helper to output the “remember me” checkbox and a label. You can style it however you like.

<?php echo $this->Form->input('rememberMe', array('type' => 'checkbox', 'label' => 'Remember me')); ?>

Depending on how your login function is implemented the code above should be used in a similar manner:

if ($this->Auth->login()) {
    // The previous piece of code goes here

    $this->redirect('/users/profile');
}

Next, add the following code in the beforeFilter() method of your AppController class( which resides in app/controller/AppController.php ) so it should look like the following:

class AppController extends Controller {
    // Our code follows from here
    public function beforeFilter() {
	// set cookie options
	$this->Cookie->httpOnly = true;
	
	if (!$this->Auth->loggedIn() && $this->Cookie->read('rememberMe')) {
	     $cookie = $this->Cookie->read('rememberMe');

             $this->loadModel('User'); // If the User model is not loaded already
	     $user = $this->User->find('first', array(
	            'conditions' => array(
	                'User.username' => $cookie['username'],
	                'User.password' => $cookie['password']
	            )
	     ));
	
	     if ($user && !$this->Auth->login($user['User'])) {
	            $this->redirect('/users/logout'); // destroy session & cookie
	     }
     }

     // The rest of AppController goes here
}

Updating the logout function accordingly. Add this to any controller which you want to handle the logout poccess. Note the use of $this->Cookie->delete(‘rememberMe’).

public function logout() {
	$this->Session->setFlash("You've been logged out");
	$this->Cookie->delete('rememberMe');
	$this->redirect($this->Auth->logout());
}

That’s it. You can go ahead and test it now. Note that I’ve tested this on CakePHP 2.2.5 but it should work on anything upwards of 2.0(inclusive)

TIP: When creating new controllers and you are overriding the beforeFilter() method you should add the following code at the beginning of your beforeFilter() method. This ensures that the last piece of code always gets executed:

parent::beforeFilter();

TIP: Remember to load the Cookies component in you AppController as follows:

public $components = array(
                    ‘Cookie’
                    // Load other components
);

 

Simple HTML slidebar – works on mobile

<!DOCTYPE html>
<html>
<head>
<style type="text/css">

#bar{
    width:200px;
    height:25px;
    border:1px solid black;
    position:relative;
}

#slider{
    width:0%;
    height:100%;
    background-color:red;
    top:0px;
    left:0px;
    position:absolute;
    cursor:pointer;
}

#info{
    width:200px;
    height:25px;
    border:1px solid black; 
}

</style>

<script type="text/javascript">
var bar, slider;

function init(){

    bar = document.getElementById('bar');
    slider = document.getElementById('slider');
    info = document.getElementById('info');
    bar.addEventListener('mousedown', startSlide, false);   
    bar.addEventListener('mouseup', stopSlide, false);
}

function startSlide(event){
    var set_perc = ((((event.clientX - bar.offsetLeft) / bar.offsetWidth)).toFixed(2));
    info.innerHTML = 'start' + set_perc + '%';  
    bar.addEventListener('mousemove', moveSlide, false);    
    slider.style.width = (set_perc * 100) + '%';    
}

function moveSlide(event){
    var set_perc = ((((event.clientX - bar.offsetLeft) / bar.offsetWidth)).toFixed(2));
    info.innerHTML = 'moving : ' + set_perc + '%';
    slider.style.width = (set_perc * 100) + '%';
}

function stopSlide(event){
    var set_perc = ((((event.clientX - bar.offsetLeft) / bar.offsetWidth)).toFixed(2));
    info.innerHTML = 'done : ' + set_perc + '%';
    bar.removeEventListener('mousemove', moveSlide, false);
    slider.style.width = (set_perc * 100) + '%';
}

</script>

</head>
<body onload='init()'>

<div id='bar'>
<div id='slider'>

</div>
</div>
<br />

<div id='info'>info</div>

</body>
</html>

 

Get proper placeholder in all browsers with jQuery

So as you know the “placeholder” attribute is supported only in the newest browsers. If you want a placeholder in all browsers you’ll need to write some JavaScript and here is how to do it.

Using my approach you’ll need to set up both the value and the title tag of the input element to the placeholder you want to use. Here is an HTML example:

<form action="" method="post" id="contact-form">
            <input type="text" name="name" id="name" value="Your name" title="Your name"/>

            <input type="text" name="subject" id="subject" value="Subject" title="Subject" />

            <input type="text" name="email" id="email" value="Your email address" title="Your email address" />

            <textarea name="msg" id="msg" title="Your message">Your message</textarea>

            <input type="submit" id="contact-form-submit" value="Send" />
</form>

Here is some css just to make it more pleasing

#contact-form textarea, #contact-form input[type=text] {
    border: none;
    padding: 10px;
    margin: 0 0 15px 0;
    box-sizing: content-box;
    -moz-box-sizing: content-box;
    -webkit-box-sizing: content-box;
    font-size: 15px;
    resize: vertical;
    background-color: rgb(197, 236, 255);
    width: 320px;
    color: rgb(0, 70, 158);
}

and here comes jQuery, watch the comments

jQuery(document).ready(function(){
    // on focusing
    jQuery('#contact-form input[type=text], #contact-form textarea').focus(function() {
        // check if the current value equals the one in the title attribute
        if ( jQuery(this).val() == jQuery(this).attr("title")) {
            // if so replace the current value with empty string or no value
            jQuery(this).val("");
        }
    });

    // on blur or the input element going out of fucus
    jQuery('#contact-form input[type=text], #contact-form textarea').blur(function() {
        // check if the current value is empty
        if ( jQuery(this).val() == "") {
            // if it is empty set the value to the text in the title attribute( restoring the placeholder )
            jQuery(this).val($(this).attr("title"));

            // this is just a beauty touch
            // when the placeholder is active set the color to something more neutral
            // so that the user can notice the difference between a placeholder and actual value
            jQuery(this).css("color", "rgb(24, 179, 255)");
        }
    });

    // this also part of the beauty touch
    // if you don't mind the color of the placeholder you can skip this
    // check if the user has just pressed a key
    jQuery('#contact-form input[type=text], #contact-form textarea').keyup(function() {
        // if so set the color to slightly darker tone
        // this is again only in order for the user to be able to make the difference
        // between a placeholder and a value easily
        jQuery(this).css("color", "rgb(0, 70, 158)");
    });
});

That’s all you need