Skip to content

bryanheo/FuelPHP-Auth-AJAX

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ok, lets assume that we have a working copy of FuelPHP with simpleauth

This code is available at: https://github.com/jsidhu/FuelPHP-Auth-AJAX

We are going to use a REST controller along with some javascript (jQuery) to end up with a working AJAX based login page.

<ol>
	<li>Download jQuery and put it in public/assets/js/jquery-1.6.1.min.js</li>
	<li>
	    Edit your template file and edit to include jquery: fuel/app/views/template.php. Add the following line to the <head> element of your template:
		<pre lang='php'><?php echo Asset::js('jquery-1.6.1.min.js'); ?></pre>
		</li>
	<li>Now, lets create a new REST controller.
	I like to keep all of my REST controller separate from my other 'normal' controllers.
	To achieve this separation, I create a folder under fuel/app/classes/controller/q and keep all of my REST controller in that directory.
	So lets start by creating a new controller by using the oil command.
        <ol>
            <li><pre lang='bash'>php oil generate controller q_auth
        Creating view: C:\jsidhu\Projects\FuelPHP-Auth-AJAX\fuel\app\views/q\auth\index.php
        Creating controller: C:\jsidhu\Projects\FuelPHP-Auth-AJAX\fuel\app\classes/controller/q\auth.php
</pre>
<br> The above command will create a new controller called 'auth' or Controller_Q_Auth in the 'q' directory located at fuel/app/classes/controller/q/auth.php. This controller is going to send us a resful response telling the browser if the user is valid or not. </li>
            <li>Now, edit the newly created controller and change:
                <pre lang='php'>class Controller_Q_Auth extends Controller_Template {</pre>
                to this:
                <pre lang='php'>class Controller_Q_Auth extends Controller_Rest {</pre>
            </li>
            <li>This would be a good time to remove the action_index method from that file as well. Its a default action created by the oil utility. We dont need it as we'll be adding our own actions.</li>
           <li>Now, lets get some things out of the way. I am assuming that you are familiar with REST and you've read some of the basics on the FuelPHP Documentation site. What we are doing here is to use a RESTful interface to check a users login/password to see if the login/pass is valid. Ok, do what does that mean? When you break it down, the process involves the browser making a POST request with your username and password, the server gets the login/password, checks the database and returns a response. Traditionally, this is in the form of a new page. What we are trying to do here to get the server to return a response in a manner that our javascript can understand. </li>
           <li>Ok, so we need to create a new action, lets call it post_check. Lets go ahead and add the following method to our controller:<pre lang='php'>public function post_check()
{
    // pull the username/password from the post data
    $username = html_entity_decode(Input::post('username'));
    $password = html_entity_decode(Input::post('password'));

    // check if the login/password is valid
    $auth = Auth::instance();
    if($auth->login($username, $password))
    {
        // username/password is valid
        $this->response(array('valid' => true, 'redirect' => '/'), 200);
    }
    else
    {
        // username/password is not valid, lets also add a little error message
        $this->response(array('valid' => false, 'error' => 'Invalid user name or password, please try again'), 200);
    }
}</pre></li>
        <li>There is a bug in FuelPHP 1.0 RC 2.1 (https://github.com/greenwebdev/core/commit/fc7ac2305a046856c4b18c0cec94ff82cea79945). We'll need to edit core/classes/controller/rest.php and change line #103 that currently reads:<pre lang='php'>$this->response->set_header('Content-Type: '.$this->_supported_formats[$this->request->format]);</pre> and change it to:<pre lang='php'>$this->response->set_header('Content-Type', $this->_supported_formats[$this->request->format]);</pre></li>
        </ol>
	</li>
	<li>Now, edit the login view for the users controller fuel/app/views/users/login.php to look something like this:
	<pre lang='javascript'><h2>Login</h2>
Login to your account using your username and password.
<?php echo isset($errors) ? $errors : false; ?>

<?php echo Form::open(array('action' => 'users/login', 'method' => 'post', 'id' => 'login-form')); ?>
<div class="input text required">
    <?php echo Form::label('Username', 'username'); ?>
    <?php echo Form::input('username', NULL, array('size' => 30, 'id' => 'username')); ?>
</div>
<div class="input password required">
    <?php echo Form::label('Password', 'password'); ?>
    <?php echo Form::password('password', NULL, array('size' => 30, 'id' => 'password')); ?>
</div>
<div class="input submit">
    <?php echo Form::submit('login', 'Login'); ?>
</div>
<div id="login-messages"></div>

<script type="text/javascript">
    $(document).ready(function()
    {
        // We'll catch form submission to do it in AJAX, but this works also with JS disabled
        $('#login-form').submit(function(event)
        {
            // Stop full page load
            event.preventDefault();

            // Check fields
            var login = $('#username').val();
            var pass = $('#password').val();

            if (!login || login.length == 0)
            {
                alert('Please enter a username.');
            }
            else if (!pass || pass.length == 0)
            {
                alert('Please enter a password.');
            }
            else
            {
                $('input[type=submit]', this).attr('disabled', 'disabled');

                // Request
                var data = {
                    username: login,
                    password: pass
                };

                // Start timer
                var sendTimer = new Date().getTime();

                // Send
                $.ajax({
                    url: '/q/auth/check',
                    dataType: 'json',
                    type: 'POST',
                    data: data,
                    success: function(data, textStatus, XMLHttpRequest)
                    {
                        // now, we get two important pieces of data back from our rest controller
                        // data.valid = true/false
                        // data.redirect = the page we redirect to on successful login
                        if (data.valid)
                        {
                            // Small timer to allow the 'checking login' message to show when server is too fast
                            var receiveTimer = new Date().getTime();
                            if (receiveTimer-sendTimer < 500)
                            {
                                setTimeout(function()
                                {
                                    document.location.href = data.redirect;

                                }, 500-(receiveTimer-sendTimer));
                            }
                            else
                            {
                                document.location.href = data.redirect;
                            }
                        }
                        else
                        {
                            $('#login-messages').html("Error: " + data.error);
                            $('input[type=submit]').removeAttr('disabled');
                        }
                    },
                    error: function(XMLHttpRequest, textStatus, errorThrown)
                    {
                        $('#login-messages').html("textStatus: " + textStatus + " and errorThrown: " + errorThrown);
                        $('input[type=submit]').removeAttr('disabled');
                    }
                });

                $('#login-messages').html('Please wait, checking login...');
            }
        });
    });

</script></pre>
	</li>
	<li>Now, copy core/config/rest.php to app/config/rest.php and edit it. Change default_format to json:<pre lang='php'>'default_format' => 'json',</pre></li>
	<li>Thats it. At this point, when you try to access the users controller, it should throw you over to the login page. Try to login, if you dont have enabled, then you should be able to use the traditional web page submit. if you have javascript enabled browser, it will not cause a page refresh to check for the login. If your login/password is good, you will be logged in and redirected to a predefined page.

	Please note that if you have not changed your routes, the default controller is 'welcome'. And since we changed the template around a bit in the last article, you will see some errors after logging in and landing at the welcome controller. This is because the welcome controller does not extend a Controller_Template or our own Controller_Common.</li>
	<li>*Edit 6/7/2011 @ 12:45pm* Here's the welcome controller modified to work with this example:
	<pre lang='php'>class Controller_Welcome extends Controller_Common {
	public function action_index()
	{
        $this->template->title = "Welcome";
		$this->template->content = View::factory('welcome/index');
	}
	public function action_404()
	{
        Log::info('ERROR 404: ' . $_SERVER['REDIRECT_URL']);
        $this->response->status = 404;
        $this->template->title = "404";
		$this->template->content = View::factory('welcome/404');
	}
}</pre></li>
</ol>

About

using FuelPHP's reset controller to implement ajax based login page..

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • PHP 100.0%