ajax code

Upload: ktik11

Post on 03-Apr-2018

220 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/28/2019 AJAX Code

    1/10

    AJAX Code

    When discussing real time communication, there arent many solutions that can rival the power of asimple webchat. What is even better, is that you already have all the tools you need to create oneyour web browser. This, coupled with the fact that this is also one of the most requested tutorials by

    Tutorialzines readers, means that it is about time to start coding. In this two-part tutorial, we will be creating an AJAX Web Chat using PHP, MySQL and jQuery. In thisfirst part, we will be discussing the PHP & MySQL side, and next week we will continue with the

    jQuery and CSS front-end. Go topart two.

    HTMLAs usual, the first step is to lay down the HTML markup. Our document is structured as HTML5 forconvenience, as this allows us to use the new, shorter (and more memorable) doctype, and skip thetype attribute on the script tags.

    ajax-chat.html

    http://tutorialzine.com/2010/10/ajax-web-chat-css-jquery/http://tutorialzine.com/2010/10/ajax-web-chat-css-jquery/http://tutorialzine.com/2010/10/ajax-web-chat-css-jquery/http://tutorialzine.com/2010/10/ajax-web-chat-css-jquery/
  • 7/28/2019 AJAX Code

    2/10

    To optimize the load time, the stylesheets are included in the head section, and the JavaScript files inthe footer, just before the closing body tag.We are using the jScrollPane plugin to create the scrollable area with the chats entries. This plugincomes with its own stylesheet, which is the first thing weve included into the page. The markup of the chat consists of four main divs the top bar, the chat container, the usercontainer and the bottom bar. The latter holds the login and submit forms. The submit form is hiddenby default and only shown if the user has successfully logged in the chat system.

    An AJAX Web Chat with PHP, MySQL and jQuery

    Lastly we include the JavaScript files. Starting with the jQuery library, we add the mousewheel plugin(used by jScrollPane), the jScrollPane plugin itself and our script.js file.

    Database SchemaBefore we move on with the PHP part, we first have to take a closer look at how the chat data isorganized in the MySQL database.For the purposes of this script we use two tables. In webchat_userswe are storing the chatparticipants. This table has na id, name, gravatarand a last_activity field. The name field isdefined as unique, so that no users have duplicate nick names in the chatroom.

    http://jscrollpane.kelvinluck.com/index.htmlhttp://demo.tutorialzine.com/2010/10/ajax-web-chat-jquery-css3/ajax-chat.htmlhttp://jscrollpane.kelvinluck.com/index.html
  • 7/28/2019 AJAX Code

    3/10

    Webchat Users Table Structure

    Another useful feature of the unique index fields, is that insert queries will fail andthe inserted_rowsproperty of the MySQLi object will be set to zero if we attempt to insert aduplicate row. This finds its place in the Chat PHP class you will see in the next step.The last_activity column holds a timestamp, which is updated every 15 seconds for every user. It isalso defined as an index, so it is faster to delete inactive users (having a last_activity column with agreater value than 15, would mean that the user is no longer viewing the chat window).

    Webchat Lines Table Structure

    The webchat_lines table holds the individual chat entries. Notice that we are storing the author name

    and gravatar here as well. This duplication is worthwhile as it frees us from using an expensive joinwhen requesting the latest chats the most frequently accessed feature of the application.The definitions of these tables are available in tables.sql in the download archive. You can executethe code in phpMyAdmin to create them. Also, when setting up the chat on your own host, rememberto modify ajax.php with your MySQL database login details.

    PHPNow that we have the database in place, lets start discussing the PHP scripts that drive the chat.The first file we are going to take a closer look at, is ajax.php. It handles the AJAX requests sent fromthe jQuery front end and outputs JSON formatted data.

    ajax.php

    require "classes/DB.class.php";

  • 7/28/2019 AJAX Code

    4/10

    require "classes/Chat.class.php";require "classes/ChatBase.class.php";require "classes/ChatLine.class.php";require "classes/ChatUser.class.php";

    session_name('webchat');

    session_start();

    if(get_magic_quotes_gpc()){

    // If magic quotes is enabled, strip the extra slashesarray_walk_recursive($_GET,create_function('&$v,$k','$v =

    stripslashes($v);'));array_walk_recursive($_POST,create_function('&$v,$k','$v =

    stripslashes($v);'));}

    try{

    // Connecting to the databaseDB::init($dbOptions);

    $response = array();

    // Handling the supported actions:

    switch($_GET['action']){

    case 'login':$response = Chat::login($_POST['name'],$_POST['email']);

    break;

    case 'checkLogged':$response = Chat::checkLogged();

    break;

    case 'logout':$response = Chat::logout();

    break;

    case 'submitChat':$response = Chat::submitChat($_POST['chatText']);

    break;

    case 'getUsers':$response = Chat::getUsers();

    break;

    case 'getChats':$response = Chat::getChats($_GET['lastID']);

    break;

    default:throw new Exception('Wrong action');

    }

    echo json_encode($response);}catch(Exception $e){

    die(json_encode(array('error' => $e->getMessage())));}

  • 7/28/2019 AJAX Code

    5/10

    For convenience, Ive used a simple switch statement to define the actions, supported by the script.These include chat submission, login/logout functionality, and actions for requesting a list of chatsand online users.

    All output is in the form of JSON messages (conveniently handled by jQuery), and errors are raised inthe form of exceptions. The switch statement routes all requests to the appropriate static method ofthe Chat class, which we will discuss later in this section.

    DB.class.php

    class DB {private static $instance;private $MySQLi;

    private function __construct(array $dbOptions){

    $this->MySQLi = @ new mysqli( $dbOptions['db_host'],$dbOptions[$dbOptions[$dbOptions[

    if (mysqli_connect_errno()) {throw new Exception('Database error.');

    }

    $this->MySQLi->set_charset("utf8");}

    public static function init(array $dbOptions){if(self::$instance instanceof self){

    return false;}

    self::$instance = new self($dbOptions);}

    public static function getMySQLiObject(){return self::$instance->MySQLi;

    }

    public static function query($q){return self::$instance->MySQLi->query($q);

    }

    public static function esc($str){return self::$instance->MySQLi-

    >real_escape_string(htmlspecialchars($str));}

    }

    The DB class is our database manager. The constructor is private, which means that no objects canbe created from the outside, and the initialization is only possible from the init() static method. Ittakes an array with MySQL login details, and creates an instance of the class, held inthe self::$instance static variable. This way we can be sure that only one connection to thedatabase can exists in the same time.The rest of the classes take advantage of the static query() method to communicate with thedatabase.

    ChatBase.class.php

    /* This is the base class, used by both ChatLine and ChatUser */

    class ChatBase{

  • 7/28/2019 AJAX Code

    6/10

    // This constructor is used by all the chat classes:

    public function __construct(array $options){

    foreach($options as $k=>$v){

    if(isset($this->$k)){$this->$k = $v;}

    }}

    }

    This is a simple base class. Its main purpose is to define the constructor , which takes an array withparameters, and saves only the ones that are defined in the class.

    ChatLine.class.php

    /* Chat line is used for the chat entries */

    class ChatLine extends ChatBase{

    protected $text = '', $author = '', $gravatar = '';

    public function save(){DB::query("

    INSERT INTO webchat_lines (author, gravatar, text)VALUES (

    '".DB::esc($this->author)."','".DB::esc($this->gravatar)."','".DB::esc($this->text)."'

    )");

    // Returns the MySQLi object of the DB class

    return DB::getMySQLiObject();}

    }

    Here is the ChatLine class. It extends ChatBase, so you can easily create an object of this class byproviding an array with a text, author, and gravatar elements. The gravatar property contains a md5hash of the persons email address. This is required so we can fetch the users gravatar fromgravatar.com.This class also defines a save method, which the object to our database. As it returnsthe MySQLi object, contained in the DB class, you can check whether the save was successful bychecking theaffected_rows property (we will come back to this in the Chat class).

    ChatUser.class.php

    class ChatUser extends ChatBase{

    protected $name = '', $gravatar = '';

    public function save(){

    DB::query("INSERT INTO webchat_users (name, gravatar)VALUES (

    '".DB::esc($this->name)."','".DB::esc($this->gravatar)."'

    )");

    return DB::getMySQLiObject();

    http://php.net/manual/en/class.mysqli.phphttp://php.net/manual/en/class.mysqli.php
  • 7/28/2019 AJAX Code

    7/10

    }

    public function update(){DB::query("

    INSERT INTO webchat_users (name, gravatar)VALUES (

    '".DB::esc($this->name)."','".DB::esc($this->gravatar)."') ON DUPLICATE KEY UPDATE last_activity = NOW()");

    }}

    The same is also valid here. We have the name and gravatar properties (notice the protected accessmodifier this means that they will be accessible in the ChatBase class, so we can set them in theconstructor).The difference is that we also have an update() method, which updatesthe last_activity timestamp to the current time. This shows that this person keeps a chat windowopen and is displayed as online in the users section.

    Chat.class.php Part 1

    /* The Chat class exploses public static methods, used by ajax.php */

    class Chat{

    public static function login($name,$email){if(!$name || !$email){

    throw new Exception('Fill in all the required fields.');}

    if(!filter_input(INPUT_POST,'email',FILTER_VALIDATE_EMAIL)){throw new Exception('Your email is invalid.');

    }

    // Preparing the gravatar hash:$gravatar = md5(strtolower(trim($email)));

    $user = new ChatUser(array('name' => $name,'gravatar' => $gravatar

    ));

    // The save method returns a MySQLi objectif($user->save()->affected_rows != 1){

    throw new Exception('This nick is in use.');}

    $_SESSION['user'] = array('name' => $name,'gravatar' => $gravatar

    );

    return array('status' => 1,'name' => $name,'gravatar' => Chat::gravatarFromHash($gravatar)

    );}

    public static function checkLogged(){

    $response = array('logged' => false);

  • 7/28/2019 AJAX Code

    8/10

    if($_SESSION['user']['name']){$response['logged'] = true;$response['loggedAs'] = array(

    'name' => $_SESSION['user']['name'],'gravatar' =>

    Chat::gravatarFromHash($_SESSION['user']['gravatar'])

    );}

    return $response;}

    public static function logout(){DB::query("DELETE FROM webchat_users WHERE name =

    '".DB::esc($_SESSION['user']['name'])."'");

    $_SESSION = array();unset($_SESSION);

    return array('status' => 1);}

    This is where all the work gets done. Remember the switch statement in ajax.php above? It maps thesupported actions with the corresponding methods from this class. Each of these methods returns anarray, as it is later converted to a JSON object with the internal json_encode() function (thishappens at the bottom of ajax.php).When the user logs in, their name and gravatar get saved as elements of the $_SESSION array, andbecome available on consecutive requests. We will be using this to validate that the user is allowed toadd chats later on.

    You can also see how we are preparing the gravatar hash. This is done according to their bestpractices guide and ensures that if the person has configured a Gravatar, it will be properly displayed.

    Chat.class.php Part 2

    public static function submitChat($chatText){if(!$_SESSION['user']){

    throw new Exception('You are not logged in');}

    if(!$chatText){throw new Exception('You haven\' entered a chat message.');

    }

    $chat = new ChatLine(array('author' => $_SESSION['user']['name'],'gravatar' => $_SESSION['user']['gravatar'],

    'text' => $chatText));

    // The save method returns a MySQLi object$insertID = $chat->save()->insert_id;

    return array('status' => 1,'insertID' => $insertID

    );}

    public static function getUsers(){if($_SESSION['user']['name']){

    $user = new ChatUser(array('name' =>$_SESSION['user']['name']));

    http://en.gravatar.com/site/implement/hash/http://en.gravatar.com/site/implement/hash/http://en.gravatar.com/site/implement/hash/http://en.gravatar.com/site/implement/hash/
  • 7/28/2019 AJAX Code

    9/10

    $user->update();}

    // Deleting chats older than 5 minutes and users inactive for 30seconds

    DB::query("DELETE FROM webchat_lines WHERE ts

  • 7/28/2019 AJAX Code

    10/10

    could potentially delete those records in getChats, but that is requested once every second and theextra processing time could severely impact the performance of our app.

    Another thing worth noting, is that, in the getChats() method, we are using the gmdate function tooutput a GMT time. In the frontend, we use the hour and minute values to feed the JavaScript dateobject, and as a result all the times are displayed in the users local time. With this the first part of this tutorial is complete!

    To be continuedGo to the second part of this tutorial, when we are building the slick jQuery & CSS3 interface andmaking it all work together.

    http://tutorialzine.com/2010/10/ajax-web-chat-php-mysql/

    http://tutorialzine.com/2010/10/ajax-web-chat-css-jquery/http://tutorialzine.com/2010/10/ajax-web-chat-php-mysql/http://tutorialzine.com/2010/10/ajax-web-chat-php-mysql/http://tutorialzine.com/2010/10/ajax-web-chat-php-mysql/http://tutorialzine.com/2010/10/ajax-web-chat-css-jquery/