Categorie
CSS JQuery PHP

Paginazione stile Facebook

Siti come Twitter o Facebook sempre all’avanguardia in fatto di tecnologia web utilizzano un effetto molto carino per visualizzare i propri risultati. Praticamente quello che vedremo è la nuova moda (ormai neanche più tanto nuova) riguardo alla paginazione dei risultati in ambiente web.
Vado a sfruttare l’effetto “real-time” che ci offre Ajax, servendomi anche di JQuery per visualizzare i vecchi risultati senza dover ricaricare la pagina, dando così un gradevole effetto di fluidità

Database

Per prima cosa ho bisogno di una base di dati che conterrà le informazioni da visualizzare. Nel mio esempio (MySQL) ho creato una semplice tabella (messages) con due campi: message_id (Auto Incrementante) e message che conterrà i dati da visualizzare.

CREATE TABLE `messages` (
  `message_id` int(10) NOT NULL AUTO_INCREMENT,
  `message` text,
  PRIMARY KEY (`message_id`)
);

CSS

body {
    font-family:Arial, 'Helvetica', sans-serif;color:#000;
    font-size:15px;
}
a {
    color:#2276BB;
    text-decoration:none;
}
* {
    margin:0px;
    padding:0px
}
ol.row {
    list-style:none
}
ol.row li {
    position:relative;
    border-bottom:1px solid #EEEEEE;
    padding:8px;
}
ol.row li:hover {
    background-color:#F7F7F7;
}
ol.row li:first-child {
}
#container {
    margin-left:60px;
    width:580px
}
 img {
    border : none ;
}
#facebook_style  {
    border:1px solid #D8DFEA;
    padding:10px 15px;
    background-color:#EDEFF4;
}
#facebook_style a {
    color:#3B5998;
    cursor:pointer;
    text-decoration:none;
    font-family:"lucida grande",tahoma,verdana,arial,sans-serif;
    font-size:11px;
    text-align:left;
}

JQuery

Questa parte è molto importante. Al click sull’ancora con classe load_more prendiamo il valore del suo attributo id. Se questo è uguale ad end allora non facciamo niente (vuol dire che non ci sono ulteriori risultati), altrimenti lanciamo una chiamata AJAX alla pagina ajax_more.php passandole l’id dell’ultimo messaggio visualizzato.

<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
$(function() {
    $('.load_more').live("click",function() {
        var last_msg_id = $(this).attr("id");
        if(last_msg_id!='end'){
            $.ajax({
                type: "POST",
                url: "ajax_more.php",
                data: "lastmsg="+ last_msg_id, 
                beforeSend:  function() {
                $('a.load_more').append('');
            },
            success: function(html){
                $(".facebook_style").remove();
                $("ol#updates").append(html);
            }
        });
    }
return false;
    });
});

Server Side (PHP)

Creiamo prima di tutto il file paginationClass.php che contiena la classe pagination, responsabile di gran parte del lavoro. Da notare che per brevità ho messo nel costruttore la parte di connessione al database. Abbiamo poi 2 metodi:

  • getMessages() che restituisce i messaggi successivi a quello con massage_id uguale al parametro passatogli.
  • printMoreBox() che stampa il box per la paginazione.

Infine con la costante MESSAGES_FOR_PAGE vado a settare il numero di risultati per pagina.

 <?php
class Pagination
{
    const MESSAGES_FOR_PAGE = 12;
    
    protected $_messages = NULL;
    protected $_dbc = NULL;
    
    public function __construct()   
    {
        /* Definisco le costanti per connessione al DB */
        DEFINE('DATABASE_USER', 'username');
        DEFINE('DATABASE_PASSWORD', 'password');
        DEFINE('DATABASE_HOST', 'localhost');
        DEFINE('DATABASE_NAME', 'messages');
        
        // Connesxsion al DB:
        $this->_dbc = @mysqli_connect(DATABASE_HOST, DATABASE_USER, DATABASE_PASSWORD, 
                DATABASE_NAME);

        if (!$this->_dbc) {
            throw new Exception('Non posso connettermi al DB');
        }             
    }

    /**
     * Getter dei messaggi dal database
     *
     * @param int $lastmsg l'id dell'ultimo messaggio
     * @return array
     */
    public function getMessages($lastmsg = 0)
    {
        if (NULL === $this->_messages) {
            $query = "SELECT * FROM messages WHERE message_id > '$lastmsg' ORDER BY message_id ASC LIMIT " . self::MESSAGES_FOR_PAGE;
            $this->_messages = mysqli_query($this->_dbc,$query);
        }
        
        return $this->_messages;
    }
    
    /**
     * Stampa i messaggi e restituisce l'id dell'ultimo messaggio
     * 
     * @param int $lastmsg l'id dell'ultimo messaggio
     * @return mixed
     */
    public function printMessages($lastmsg = 0)
    {
        while($row=mysqli_fetch_array($this->getMessages($lastmsg),MYSQLI_ASSOC))
        { 
            $msg_id  = $row['message_id'];
            $message = $row['message'];
            
            echo "
  • $message
  • "; } return isset ($msg_id) ? $msg_id : 'end'; } /** * Stampa a video il box per visualizzare in nuovi messaggi. * * @param int $lastmsg l'id dell'ultimo messaggio */ public function printMoreBox($lastmsg) { if( mysqli_num_rows($this->getMessages()) == self::MESSAGES_FOR_PAGE) { echo ''; } else { echo ''; } } } ?>

    Fatto questo poi è un gioco da ragazzi; basta includere paginationClass.php nelle nostre pagine, istanziare un oggetto e richiamarne i metodi. Vediamo:

    <?php
    include('paginationClass.php');
    ?>
    <?php
    try {
    ?> 
    <ol class="row" id="updates">
    <?php
    $pagination = new Pagination();
    $lastmsg = $pagination->printMessages();
    ?>
    </ol>
    <?php 
    $pagination->printMoreBox($lastmsg);   
    } catch (Exception $exc) {
        echo $exc->getMessage();
    }
    ?>
    

    Questa è infine la pagina ajax_more.php che sarà chiamata attarverso una richiesta AJAX. Da notare (come per la precedente) la semplicità e brevità del codice.

    <?php
    include('paginationClass.php');
    
    if(isset($_POST['lastmsg']) &&is_numeric($_POST['lastmsg']))
    {
        $lastmsg    = $_POST['lastmsg'];
        $pagination = new Pagination();
        $lastmsg    = $pagination->printMessages($lastmsg);
        $pagination->printMoreBox($lastmsg);
    }
    ?>
    

    Live Demo

    live demo

    12 risposte su “Paginazione stile Facebook”

    Scusa ma mi sto scervellando. Nella PaginationClass se volessi recuperare la variabile presente in una query (tipo pagina.php?id=10 dove 10 è la variabile) come la recupero dal database?

    Ho provato con $query = “SELECT * FROM messages WHERE id > ‘$lastmsg’ AND uid = ‘$VARIABILE’

    ma non funziona!
    Ti prego di un aiuto
    Grazie

    Aggiungo che ho effettuato le seguenti modifiche:

    if(isset($_POST[‘lastmsg’]) && is_numeric($_POST[‘lastmsg’]) && isset($_POST[‘profileid’]))
    {
    $lastmsg = $_POST[‘lastmsg’];
    $VARIABILE = $_POST[‘VARIABILE’];
    $pagination = new Pagination();
    $lastmsg = $pagination->printMessages($lastmsg,$profileid);
    $pagination->printMoreBox($lastmsg,$profileid);

    }

    e

    $(function() {
    $(‘.load_more’).live(“click”,function() {
    var last_msg_id = $(this).attr(“id”);
    var profileid = “”;
    if(last_msg_id!=’end’){
    $.ajax({
    type: “POST”,
    url: “wall_more.php”,
    data: “lastmsg=”+ last_msg_id +”&VARIABILE=”+ VARIABILE,
    beforeSend: function() {
    $(‘a.load_more’).append(”);
    },
    success: function(html){
    $(“.mci_pag_style”).remove();
    $(“#profile_pagination”).append(html);
    }
    });
    }
    return false;
    });
    });

    Non so se ho capito bene, vorresti restringere ulteriormente la query con un parametro, eventualmente, passato via querystring tipo index.php?uid=a (dove index.php è la prima pagina)
    Ci sono vari modi per ottenere il risultato, il più semplice e veloce che mi viene in mente è usare le sessioni del server. Fai le seguenti modifiche al mio script:
    fai iniziare le pagine index.php ed ajax_more.php con:

    session_start();
    

    poi modifica il metodo getMessages() così:

        public function getMessages($lastmsg = 0)
        {
            if (NULL === $this->_messages) {
                $queryExtended = isset($_SESSION['uid']) ? "AND uid = '{$_SESSION['uid']}'" : "";
                $query = "SELECT * FROM messages WHERE message_id > '$lastmsg' $queryExtended ORDER BY message_id ASC LIMIT " . self::MESSAGES_FOR_PAGE;
    
                $this->_messages = mysqli_query($this->_dbc,$query);
            }
            
            return $this->_messages;
        }  
    

    Ti ringrazio. Io però devo recuperare i dati da un _GET e non da un _SESSION comunque ho modificato lo script così e sembra funzionare.

    if (NULL === $this->_messages) {
    $queryExtended = isset($_GET[‘uid’]) ? “AND uid = ‘{$_GET[‘uid’]}'” : “”;
    $query = “SELECT * FROM messages WHERE message_id > ‘$lastmsg’ $queryExtended ORDER BY message_id ASC LIMIT ” . self::MESSAGES_FOR_PAGE;
    $this->_messages = mysqli_query($this->_dbc,$query);
    }

    Hai ragione, mi ero dimenticato di postarti una riga. Nell’index.php devi aggiungere anche:

    $_SESSION['uid'] = isset($_GET['uid']) ? $_GET['uid'] : NULL;
    

    Così ad occhio, con il tuo script hai bisogno di passare il parametro via GET anche con la chiamata AJAX, si può fare ma è una complicazione.

    Effettivamente se metto DESC LIMIT si scompagina tutto. Anzitutto non considera più il filtro $_GET[‘id’] impostato e poi gli id non vanno in ordine decrescente, ma al cambio pagina non riparte in maniera sequenziale (l’id non è ad esempio 3 -> 2 -> 1 ma 3 -> 2-> 3).

    Se vuoi fare l’ordinamento discendente allora nella pagina iniziale devi passare al costruttore ed al metodo printMessages() l’ID dellultimo record (che recuperi tramite query) oppure se non ti vuoi rompere le scatole (ma è poco professinale) un valore molto alto tipo:

    //....
    $pagination = new Pagination(99999);
    $lastmsg = $pagination->printMessages(99999);
    //....
    

    poi cambi il segno della query da > a <:

    $query = “SELECT * FROM messages WHERE message_id < '$lastmsg' $queryExtended ORDER BY message_id DESC LIMIT " . self::MESSAGES_FOR_PAGE;
    

    Riprendo il tuo post:

    Così ad occhio, con il tuo script hai bisogno di passare il parametro via GET anche con la chiamata AJAX…

    Intendi che in ajax_more dovrei aggiungere una variabile? Ma il metodo utilizzato lì non è POST?

    Se fai quello che ho scritto, cioè lo assegni subito ad un sessione, eviti di sbatterti troppo. Altrimenti devi gestire il passaggio di quel filtro anche sul JavaScript.

    Ciao
    perdonami ma non riesco a fare ciò che hai suggerito per effettuare la visualizzazione dei record con DESC?

    quando dici questo:
    “Se vuoi fare l’ordinamento discendente allora nella pagina iniziale devi passare al costruttore ed al metodo printMessages() l’ID dellultimo record (che recuperi tramite query)..”

    preumo che intendi nel pezzo di codice che si inserisce dove si vuole visualizzare la paginazione?
    quindi dove c’è questo codice:

    printMessages();
    ?>

    printMoreBox($lastmsg);
    } catch (Exception $exc) {
    echo $exc->getMessage();
    }

    se così fosse, io pensavo di risolvere inserendo $lastmsg all’interno di:
    $pagination = new Pagination();
    $lastmsg = $pagination->printMessages();

    posti poco più sopra.. ma nn funziona..

    Scusa la mia ignoranza, come faccio a fargli passare l’ultimo id? :/

    Lascia un commento

    Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

    Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.