Cómo crear un shoutbox con PHP y jQuery

En este tutorial, vamos a crear un shoutbox con PHP y jQuery, que permita a los visitantes de tu sitio web dejarse pequeños comentarios entre ellos. Los mensajes se almacenarán en el servidor como archivos, no necesitaremos el uso de una base de datos como MySQL. Vamos a utilizar dos librerías de PHP para hacer las cosas más fáciles - Flywheel para almacenar los mensajes como archivos JSON y RelativeTime para la creación de timestamps legibles. Claro está, utilizaremos Composer para instalar esas librerías.

Del lado del cliente utilizaremos jQuery, y la librería Emoji One, la cual es un proyecto libre e ideal para añadir emojis en aplicaciones web. ¿Lo tenemos todo? ¡Pues vamos a empezar!

El HTML

Vamos a empezar con el index.html. Es un documento HTML5 normal, que incluye nuestras librerías de JavaScript, los scripts y las hojas de estilo. Estas son las partes relevantes del shoutbox:

index.html

<div class="shoutbox">
    
    <h1>Shout box <img src='./assets/img/refresh.png'/></h1>
    
    <ul class="shoutbox-content"></ul>
    
    <div class="shoutbox-form">
        <h2>Write a message <span>×</span></h2>
        
        <form action="./publish.php" method="post">
            <label for="shoutbox-name">nickname </label> <input type="text" id="shoutbox-name" name="name"/>
            <label class="shoutbox-comment-label" for="shoutbox-comment">message </label> <textarea id="shoutbox-comment" name="comment" maxlength='240'></textarea>
            <input type="submit" value="Shout!"/>
        </form>
    </div>
    
</div>

Con JavaScript vamos a insertar los mensajes publicados en el elemento ul. El formulario se oculta de forma predeterminada, y sólo se muestra cuando se hace clic en el "Escribe un mensaje" de la cabecera.

El código Javascript

Y aquí está nuestro script.js, que se encarga del trabajo del HTML anterior:

script.js

$(function(){

    // Storing some elements in variables for a cleaner code base

    var refreshButton = $('h1 img'),
        shoutboxForm = $('.shoutbox-form'),
        form = shoutboxForm.find('form'),
        closeForm = shoutboxForm.find('h2 span'),
        nameElement = form.find('#shoutbox-name'),
        commentElement = form.find('#shoutbox-comment'),
        ul = $('ul.shoutbox-content');

    // Replace :) with emoji icons:
    emojione.ascii = true;

    // Load the comments.
    load();
    
    // On form submit, if everything is filled in, publish the shout to the database
    
    var canPostComment = true;

    form.submit(function(e){
        e.preventDefault();

        if(!canPostComment) return;
        
        var name = nameElement.val().trim();
        var comment = commentElement.val().trim();

        if(name.length && comment.length && comment.length < 240) {
        
            publish(name, comment);

            // Prevent new shouts from being published

            canPostComment = false;

            // Allow a new comment to be posted after 5 seconds

            setTimeout(function(){
                canPostComment = true;
            }, 5000);

        }

    });
    
    // Toggle the visibility of the form.
    
    shoutboxForm.on('click', 'h2', function(e){
        
        if(form.is(':visible')) {
            formClose();
        }
        else {
            formOpen();
        }
        
    });
    
    // Clicking on the REPLY button writes the name of the person you want to reply to into the textbox.
    
    ul.on('click', '.shoutbox-comment-reply', function(e){
        
        var replyName = $(this).data('name');
        
        formOpen();
        commentElement.val('@'+replyName+' ').focus();

    });
    
    // Clicking the refresh button will force the load function
    
    var canReload = true;

    refreshButton.click(function(){

        if(!canReload) return false;
        
        load();
        canReload = false;

        // Allow additional reloads after 2 seconds
        setTimeout(function(){
            canReload = true;
        }, 2000);
    });

    // Automatically refresh the shouts every 20 seconds
    setInterval(load,20000);


    function formOpen(){
        
        if(form.is(':visible')) return;

        form.slideDown();
        closeForm.fadeIn();
    }

    function formClose(){

        if(!form.is(':visible')) return;

        form.slideUp();
        closeForm.fadeOut();
    }

    // Store the shout in the database
    
    function publish(name,comment){
    
        $.post('publish.php', {name: name, comment: comment}, function(){
            nameElement.val("");
            commentElement.val("");
            load();
        });

    }
    
    // Fetch the latest shouts
    
    function load(){
        $.getJSON('./load.php', function(data) {
            appendComments(data);
        });
    }
    
    // Render an array of shouts as HTML
    
    function appendComments(data) {

        ul.empty();

        data.forEach(function(d){
            ul.append('<li>'+
                '<span class="shoutbox-username">' + d.name + '</span>'+
                '<p class="shoutbox-comment">' + emojione.toImage(d.text) + '</p>'+
                '<div class="shoutbox-comment-details"><span class="shoutbox-comment-reply" data-name="' + d.name + '">REPLY</span>'+
                '<span class="shoutbox-comment-ago">' + d.timeAgo + '</span></div>'+
            '</li>');
        });

    }

});

La librería Emoji One cuenta con versión para PHP y Javascript. En el método appendComments, utilizamos la función emojione.toImage() para convertir todos los smileys introducidos en emojis estándar. Fíjate que todas las funciones son compatibles, y echa un vistazo a esta práctica web de emojis. Ahora que la interfaz está lista, vamos a por el backend.

El código PHP

Tenemos dos archivos, publish.php y load.php. El primero acepta una petición POST para almacenar mensajes en el almacén de datos, y el segundo devuelve los 20 últimos mensajes. Estos archivos no se utilizan directamente por los visitantes, sino que se ejecutan en peticiones AJAX.

publish.php

<?php

// Include our composer libraries
require 'vendor/autoload.php';

// Configure the data store

$dir = __DIR__.'/data';

$config = new JamesMossFlywheelConfig($dir, array(
    'formatter' => new JamesMossFlywheelFormatterJSON,
));

$repo = new JamesMossFlywheelRepository('shouts', $config);
    
// Store the posted shout data to the data store

if(isset($_POST["name"]) && isset($_POST["comment"])) {
    
    $name = htmlspecialchars($_POST["name"]);
    $name = str_replace(array("n", "r"), '', $name);

    $comment = htmlspecialchars($_POST["comment"]);
    $comment = str_replace(array("n", "r"), '', $comment);
    
    // Storing a new shout

    $shout = new JamesMossFlywheelDocument(array(
        'text' => $comment,
        'name' => $name,
        'createdAt' => time()
    ));
    
    $repo->store($shout);
    
}

load.php

<?php

require 'vendor/autoload.php';

// If you want to delete old comments, make this true. We use it to clean up the demo.
$deleteOldComments = false;

// Setting up the data store

$dir = __DIR__.'/data';

$config = new JamesMossFlywheelConfig($dir, array(
    'formatter' => new JamesMossFlywheelFormatterJSON,
));

$repo = new JamesMossFlywheelRepository('shouts', $config);

// Delete comments which are more than 1 hour old if the variable is set to be true.

if($deleteOldComments) {
    
    $oldShouts = $repo->query()
                ->where('createdAt', '<', strtotime('-1 hour'))
                ->execute();

    foreach($oldShouts as $old) {
        $repo->delete($old->id);
    }
    
}

// Send the 20 latest shouts as json

$shouts = $repo->query()
        ->orderBy('createdAt ASC')
        ->limit(20,0)
        ->execute();

$results = array();

$config = array(
    'language' => 'RelativeTimeLanguagesEnglish',
    'separator' => ', ',
    'suffix' => true,
    'truncate' => 1,
);

$relativeTime = new RelativeTimeRelativeTime($config);
        
foreach($shouts as $shout) {
    $shout->timeAgo = $relativeTime->timeAgo($shout->createdAt);
    $results[] = $shout;
}

header('Content-type: application/json');
echo json_encode($results);

Con esto nuestro shoutbox estaría listo. Puedes embeberlo en cualquier sitio web, personalizarlo y cambiar el código interno cada vez que te plazca. Esperamos que te haya gustado.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP