sábado, 9 de abril de 2011

Tutorial: Crea tu aplicacion de chat con codeigniter(php) y jquery ajax

 En el desarrollo web con codeigniter y jquery una de las primeras dudas que siempre surgen es como usar el jquery ajax con codeigniter, es uper sencillo y aquí les muestro un tutorial de como crear un chat con codeigniter y jquery ajax, este tutorial es inspirado en este tutorial, lo e echo también para que puedan hacer una comparación entre programar solo con php o programar con un framework. El chat que vamos a crear es muy sencillo y no trabaja con base de datos, pero para empezar a aprender sera muy util, después lo mejorare e ire publicando.



Introduccion:

Primero vamos a definir como va a ser la lógica de nuestro chat, el usuario entra a nuestro chat, el cual le va a mostrar un formulario para hacer login, cuando el usuario envie el formulario el sistema comprobara que halla especificado un nombre y después establecera una variable de sesión con el nombre del usuario lo enviara a el chat, el cual ara la comprobacion de que este establecido la variable de sesión con el nombre del usuario y mostrara el chat, el chat debe tener además de la función principal dos funciones mas una para mostrar el historial del chat y otra para agregar los mensajes que el usuario envié. Todo el historial se guardara en un solo archivo el cual sera que se le muestre al usuario.

Primer paso: Creando las vistas.

Aunque este tutoríal es muy sencillo, vamos a crear 4 vistas, 2 vistas serán el template, y las otras dos serán una para el login y la otra para el chat como tal.

Aquí les dejo los códigos de cada una de las vistas:

header.php

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN" “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Codeignier chat</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
</head>
<body>


footer.php

</body>
</html>

El footer y el header van a ser iguales tanto en el login como en el chat, estos dos solo incluyen la estructura del html y la referencia a el script de jquery.

login.php

<div id="loginform">
<form>
<p>Por favor introdusca su nombre para continuar:</p>
<label for="name">Nombre: </label>
<input type="text" name="name" id="name" />
<input type="submit" name="enter" id="enter" value="Enter" />
</form>
</div>
<style>
*{margin:0;padding:0; text-align:center;}
#loginform {
margin:0 auto;
padding-bottom:25px;
background:#EBF4FB;
border:1px solid #ACD8F0; }

#loginform { padding-top:18px; }

#loginform p { margin: 5px; }
</style>

En el formulario de login el usuario especificara cual es el nombre de usuario que desea usar.

chat.php

<style>
    /* CSS Document */
    body {
    font:12px arial;
    color: #222;
    text-align:center;
    padding:35px; }

    form, p, span {
    margin:0;
    padding:0; }

    input { font:12px arial; }

    a {
    color:#0000FF;
    text-decoration:none; }

    a:hover { text-decoration:underline; }

    #wrapper {
    margin:0 auto;
    padding-bottom:25px;
    background:#EBF4FB;
    width:504px;
    border:1px solid #ACD8F0; }
    #chatbox {
    text-align:left;
    margin:0 auto;
    margin-bottom:25px;
    padding:10px;
    background:#fff;
    height:270px;
    width:430px;
    border:1px solid #ACD8F0;
    overflow:auto; }

    #usermsg {
    width:395px;
    border:1px solid #ACD8F0; }

    #submit { width: 60px; }

    .error { color: #ff0000; }

    #menu { padding:12.5px 25px 12.5px 25px; }

    .welcome { float:left; }

    .logout { float:right; }

    .msgln { margin:0 0 2px 0; }
</style>
<div id="wrapper">
<div id="menu">
<p class="welcome">Bienvenido, xxxx<b></b></p>
<p class="logout"></p>
<div style="clear:both"></div>
</div>
<div id="chatbox"></div>
<input name="usermsg" type="text" id="usermsg" size="63" />
<input name="submitmsg" type="button"  id="submitmsg" value="Enviar" />
</div>

Este es el chat, ya de una ves con el estilo, en <p class='welcome'> bienvenido </p> es donde ira el nombre del usuario, en <p class="logout"></p> es donde ira el link para salir de la aplicacion, ya al final dos input uno tipo text, para que el usuario especifique el mensaje que desea enviar y el otro un boton simple para enviar el texto.

Paso 2:  Creando el login.

Bueno lo primero sera crear un controlador llamado login.php, y modificar en /application/config/routes.php y poner como controlador pre establecido($route['default_controller']) en login. De acuerdo a la lógica de lo que hay que hacer, debemos primero crear nuestra función index, y empezar cargando la libreria de sesión($this->load->library('session');) y el helper form ($this->load->helper('form');), despues continuamos cargando nuestra vista($this->load->view('login')), por supuesto tenemos que cargar las tres vistas header, login y footer, al usar la función $this->load->view se envían directamente como salida al navegador. la función index debería quedarnos así:

function index()
{
    $this->load->library('session');
    $this->load->helper('form');

    $this->load->view('header');
    $this->load->view('login');
    $this->load->view('footer');
}

También debemos crear una función más en nuestro controlador una llamada submit, donde se registra el nombre del usuario y se redireccionara a el chat.  Para comenzar nuestra función debemos meter en una variable el parametro enviado por post, con la libreria input que ya esta pre-cargada por defecto en codeigniter usando la funcion $this->input->post(), despues comprobar que no este vacio, y si esta vacia redireccionar al formulario de login, sino, establecer la variable de sesion($this->session->set_userdata();) con el nombre elegido por el usuario y redireccionamos al chat. Para redireccionar vamos a usar la función redirect() que pertenece a la url helper,

function submit()
{
        $name = $this->input->post('name');
        if(!empty($name))
        {
            $this->session->set_userdata('name',$name);
            redirect('/chat');
        }
        else
        {
            redirect('/login');
        }
}

Para no tener que estar cargando en cada funcion las diferentes librerias y helpers que vamos a necesitar, vamos a crear la funcion contructora y de hay los cagaremos:

    function __construct()
    {
        parent::__construct();
        $this->load->library('session');
        $this->load->helper('url');
        $this->load->helper('form');
    }

Paso 3: Estructurando el chat.

En el chat ya tenemos dispuesto un area donde vamos imprimir el nombre que el usuario eligio, con esta simple linea de codigo imprimiremos el nombre del usuario <?php echo $this->session->userdata('name'); ?>.

Tambien dispusimos un area donde esta el link de salida del chat donde crearemos el link con la funcion anchor que proviene de el helper url, pondremos <?php echo anchor('/chat/logout', 'Salir del chat.', "id='exit'") ?>, el primer parametro es a donde va a estar dirigido el enlace, el segundo es el texto que va a mostrar y el tercer parametro permite especificar atributos a el enlace, el atributo id  lo agregamos para crear una funcion para que parescar un cuadro de dialogo de confirmacion para salir del chat, para crear esta funcion debemos crear la etiqueta script y adentro colocar:

$(document).ready(function(){ 
    $('#exit').click(function(event){ 
        var exit = confirm('Esta seguro que deseas salir?');
        // con esta funcion aparecera un cuadro de confirmacion
        if(exit==false){return false;}
        // si la persona marco cancelar, la funcion devolvera false y se cancelara.
    });
});

Paso 4: Dandole vida al chat.

Ahora debemos darle vida a nuestro chat, para trabajar con archivos vamos a usar el helper file que trae codeigniter, primero debimos crear una carpeta en la ruta principal que la vamos a llamar chat y adentro crearemos un archivo llamado chat.html, completamente vacio hay guardaremos el historial del chat. De el helper file vamos a usar mas que todo estas dos funciones, read_file('./chat/chat.html') para leer el contenido del archivo y write_file('./chat/chat.html','lo que se le va a agregar al archivo','a'); para escribir al archivo, lo importante de destacar de esta funcion es que en el tercer parametro definimos el modo en que se va a escribir el archivo, el modo a simplemente agregara el texto al final del archivo, para mas informacion sobre lo modos aqui!.

Entonces en la vista agregaremos la funcion para leer el archivo dentro de <div id="chatbox"></div>.

Ahora si creamos el controlador chat, donde crearemos para empezar dos funciones el contructor y el index, en el contructor comprobaremos que este definido la variable de sesion con el nombre sino redirecionaremos al login, y en el index simplemente mostramos el chat.

    function __construct()
    {
        parent::__construct();
        $this->load->library('session');
        $this->load->helper('url');
        $this->load->helper('file');
        if(empty($this->session->userdata('name')))
        {
            redirect('/login');
        }
    }

    function index()
    {
        $this->load->view('header');
        $this->load->view('chat');
        $this->load->view('footer');
    }

Y la funcion actualizar donde el chat recibira el historial del chat.

function actualizar()
{
    echo read_file('./chat/chat.html');
}

Paso 5: Manejando las entradas del usuario.

Una vez que el usuario escriba el mensaje, deseamos tomar su entrada y escribirla en nuestro log de chat. Para lograr esto, debemos usar jQuery y codeigniter para sincronizar por ajax la informacion del lado del cliente y del servidor.

Jquery

En la vista del chat debemos agregar la funcion para que al hacer click en enviar se envie el contenido del input de usermsg a nuestro controlador y haci se agrege la entrada, esto se basara en la funcion post de jquery.

     $('#submitmsg').click(function(event){
        event.preventDefault(); //previene cualquier otro evento del boton.
        var clientmsg = $('#usermsg').val(); //obtiene el valor del input
        $.post('<?php echo site_url('/chat/agregar');?>', {mensaje: clientmsg});
       //hace la llamada ajax a el controlador, y envia  por post el mensaje
        $('#usermsg').attr('value', '');//limpia el input.
    });

Codeigniter

Para manejar las entradas del usuario debemos crear en el controlador de chat la funcion agregar.
Donde se agregara a nuestro chat el mensaje que el usuario escribio.

function agregar()
{
    $mensaje = "<div class='msgln'>(".date("g:i A").")  <b>".$this->session->userdata('name')."</b>:  ".$this->input->post('mensaje')."<br></div>";
    write_file('./chat/chat.html', $mensaje, 'a');
}

Paso 6: Mostrando el historial del chat

Después que se agrega el mensaje del usuario al historial del chat ahora ahi que poder mostrarlo al usuario, esto se hace también con una llamada ajas de jquery y una función en nuestro controlador de codeigniter


Solicitud por ajax del historial.

Esta solicitud es lo principal de nuestro sistema ya que esta le mostrara que es lo que a escrito el y lo que an escrito los demás usuarios, que es la base de cualquier chat.

En esta petición haremos la solicitud con la función ajax de jquery y pondremos el resultado en el div chatbox, esta funcion la vamos a enmarcar dentro de otra, la función nos quedaría así:

 $.ajax({
    type: "post",
    url: "<?php echo site_url('/chat/actualizar');?>",
    success: function(msg){
        $('#chatbox').html(msg);
    }
});

Auto-scrolling.

Como puede que hayan visto en otras aplicaciones de chat, el contenido automáticamente hace scroll hacia abajo si el contenedor del log de chat (#chatbox) se llena. Nosotros implementaremos una función simple y similar, que comparará la altura del scroll del contenedor antes y después de que hagamos la petición Ajax. Si la altura del scroll es mayor después de la petición, usaremos un efecto animado jQuery para hacer scroll en el div #chatbox.

    function loadLog(){
        var oldscrollHeight = $('#chatbox').attr('scrollHeight') - 20;
        $.ajax({
            type: "POST",
            url: "<?php echo site_url('/chat/actualizar');?>",
            success: function(msg){
                $('#chatbox').html(msg);
                var newscrollHeight = $('#chatbox').attr('scrollHeight') - 20; //La altura del scroll después del pedido
                if(newscrollHeight > oldscrollHeight){
                    $('#chatbox').animate({ scrollTop: newscrollHeight }, 'normal'); //Autoscroll hacia el fondo del div
                }
            }
        });
    } 

Primero almacenamos la pocisión del scroll antes de la solicitud, después de la solicitud almacenamos la nueva pocisión y si la nueva pocision es mayor que la vieja con la función animate hará una animación para bajar la pocisión de la ventana al final de la misma.

Ahora para actualizar constantemente el contenido del chat debemos usar la funcion setInterval, la cual cada cierto tiempo ejecutara la funcion loadLog, el segundo parametro especificara cada cuanto tiempo cargara la función.




Aqui esta el archivo completo: http://www.box.net/shared/q3hrklaca1.

Pd: Para evitar ataques xss, es bueno que activen el filtro xss general. Poniendo la variable $config['global_xss_filtering'] en true en el archivo /application/config/config.php.

18 comentarios:

  1. Excelente tutorial Mariano, hace poco empecé con CodeIgniter y tu blog es uno de los que más me ayudan, muchas gracias y seguí así.

    Agregado: Estaría bueno para completar el login utilizar la librería 'form_validation'.

    ResponderEliminar
  2. jejeje, gracias por el comentario.

    Si tienes toda la razon, cuando estaba haciendo el tutorial estaba pensando en eso mismo, tambien pienso despues agregarle jquery ui dialog, integrarlo con una base de datos y otras mejoras más e irlas publicando.

    ResponderEliminar
  3. La primera vez que visito tu blog.
    Me encanta ver codigo de gente que está acostumbrado a trabajar con codeigniter. Es justo lo que buscaba.
    Quizá esté un poco desorganizado, pero la funcionalidad es correcta.
    ¿Es tuyo el código?

    Si necesitas algo de código, preguntame que tengo buenos hechos por mi.

    Por cierto, como haces funcionar el AJAX con el XSS. ¿Tienes modificado el filtro para que se lo salte?

    El uso de la base de datos para que lo quieres hacer, para almacenar sesiones de chat, en lugar de guardar el fichero?

    Ahora pronto tengo que montar uno, utilizare parte de tu código de base. Cuando lo tenga decente te lo enseño.

    saludos

    ResponderEliminar
  4. hola ve, si el codigo lo hice yo, hace ya un año. Yo mejorare el codigo del chat. lo que pasa es que despues me dio flojera publicarlo y lo debo tener por ahi perdido, pero lo voy a buscar y te lo envio para que veas que fue lo que hice.

    ResponderEliminar
  5. Hola, funciona perfecto, pero como podria funcionar esto para una pagina web, para que chateen los usuarios que esten registrados?
    Espero tu respuesta, de antemano muchas gracias, y nuevamente, muy bueno el tuto!!

    ResponderEliminar
    Respuestas
    1. Pues debes conectarlo con tu libreria de login, y el nombre que va a mostrar seria solamente el nombre del usuario en la db, pero depende de que sistema tengas y montado.

      Eliminar
  6. Mmmm, mire lo que tengo es un proyecto en codeigniter el cual tiene un sistema de login que tendra a tipos de acceso segun sus privilegios precisamente el siguiente:

    http://sourcezilla.com/articulos/internet/como-restringir-a-los-usuarios-el-acceso-a-diferentes-partes-de-una-aplicacion.html#comments

    ¿Como se podría integrar su chat a el login del proyecto que le mencione?
    ¿pueden chatear todos solo con la condicion de que esten logeados?
    Espero me pueda ayudar...se lo agradecería un monton...
    Le podria enviar un correo para comunicarme con usted?
    Muchas gracias de antemano.
    Saludos!

    ResponderEliminar
    Respuestas
    1. Si me puedes enviar un correo, y para hacerlo seria sencillo, simplemete usa un if para comprobar que el usuario este logeado antes de hacer cualquier cosa, if (isset($this->session->userdata['logged_in'])

      Y despues muestras el nombre de usuario y listo, no seria muy complicado.

      Eliminar
  7. Como le hago para obtener su correo, le adjunto el mio para que envie un ok y poder enviarle los archivos, se lo agradecería mucho amigo.
    raullrich@gmail.com
    O disculpe le dejo el proyecto codeigniter para si pudiese ayudar o indicar que debería hacer para poder integrar un sistema de chat básico, con mucha humildad espero su respuesta, muchos saludos amigo.

    ResponderEliminar
    Respuestas
    1. Aqui esta el proyecto http://db.tt/3DVo93VL
      Ojala pueda ayudarme que llevo varias semanas tratando de integrar algun chat no logrando nada

      Eliminar
  8. Hola, amigos quería preguntar como hago para poder crear el efecto que la etiqueta "title", titile como facebook, cuando llega un mensaje nuevo, cuando la venta del chat se encuentre minimizada, ojala alguien me pueda ayudar.

    ResponderEliminar
  9. hola una pregunta yo tambien estoy con la idea de implementar el chat en un sitio pero mi duda es de que forma crear grupos de chat para evitar que todos puedan ver sus mensajes a lo que me refiero es que en mi caso tengo varias areas de trabajo ojala puedan darme una idea....

    ResponderEliminar
  10. ojala pueda ayudarme la idea principal es algo como eso añadir un comentario (respuesta). en las areas de trabajo de mi sitio hay varios puestos del inferior le contesta a su superior al momento que da su respuesta pueda visualizarse al momento en su vista y pueda editarlo para reenviar nuevamente a su superior.

    ResponderEliminar
    Respuestas
    1. lo que podrias es añadir la funcionalidad de chats pivado para lograr lo que quieres hacer, se me ocurre una tabla nueva donde esten identificados dos usuarios, el que envia el mensjae y quien lo recibe. y haces un cuadro similar al anterior con los mensajes que le envian y con los que el envia y listo. seria similar a lo que deseas hacer...

      Eliminar
  11. no tienes los archivos para descargarlos? no entiendo donde poner la funcion ajax que consulta el historial, gracias

    ResponderEliminar
  12. buenas tardes tendra algun ejemplo asi en yii?

    ResponderEliminar