Paginare perfecta in php
Paginare perfecta in php
Paginarea este un subiect care a fost discutat si ras-discutat - pot fi gasite zeci de articole si referinte catre cu si catre clase care se ocupa de prelucrarea seturilor de rezultate.
Unele clase pentru paginare necesita parametri, ca de exemplu resurse din baze de date si una sau mai multe instructiuni SQL ce urmeaza a fi transmise constructorului. Claselor care folosesc aceasta metoda le lipseste flexibilitatea - ce te faci daca ai nevoie de formatare diferita pentru numerel paginilor in antet-ul si in subsolul paginii ? Te apuci si modifici functia care face output, sau sublcasa sau intreaga clasa doar pentru a modifica respectiva metoda ?
Aceste "solutii" sunt restrictive si nu incurajeaza reutilizarea codului.Acest tutorial isi propune sa abstractizeze o clasa care sa se ocupe de managementul rezultatelor, implicit renuntarea la dependinta de conexiuni la baza de date sau cereri SQL. Metoda discutata in acest tutorial ii permite dezvoltatorului / programatorului sa isi creeze propriile sale layout-uri si sa le inregistreze pur si simplu folosind un pattern orientat pe obiecte, cunoscut sub numele de Strategy Design Pattern
Ce este Strategy Design Pattern ?
Sa consideram urmatoarele: ai in site-ul tau o sumedenie de pagini pentru care rezultatele dintr-un query sunt paginate. Site-ul tau foloseste o functie sau o clasa care se ocupa de obtinerea rezultatelor si afisarea lor in pagina.Toate bune si frumoase, pana in momentul in care te decizi sa schimbi layout-ul link-urilor de paginare, pe una sau mai multe pagini. Pentru a obtine rezultatul dorit va trebui sa modifica metoda careia i-a fost incredintata aceasta responsabilitate.
O solutie mai buna ar fi sa oricate layout-uri doresti si sa folosesti, dinamic, unul in momentul afisarii paginii. Strategy Design Pattern iti permite sa faci exact acest lucru. Pe scurt, Strategy Design Pattern este un design pattern orientat pe obiecte, utilizat de o clasa care vrea/poate sa-si schimbe comportamentul la rulare.
Folosind capabilitatile polimorfice ale PHP-ului, o clasa generala (asa cum este cea pe care o vom construi in acest articol) foloseste un obiect care implementeaza o interfata, si defineste implementari concrete pentru metodele definite in acea interfata.In timp ce o interfata nu poate fi instantiata, ea poate referentia clase care o implementeaza. Deci, cand cream un layout nou, putem lasa strategia sau interfata din clasa ce paginare sa referentieze layout-urile, dinamic, la rulare. Apelarile care produc link-urile paginarii vor produce deci pagina care este randata cu layout-ul referentiat in momentul respectiv.
Fisiere necesare
Dupa cum am mentionat, acest tutorial nu se ocupa de modul in care rezultatele sunt paginate ci de cum sa folosim o interfata pentru a implementa aceasta logica pastrand flexibilitatea. Ca punct de pornire, este dispobilia o clasa ce contine functionalitaea pentru a inregistra array-uri primitive sau obiecte - clasa Paginated - si de asemenea o interfata pe care o vor layout-urile trebuie sa o implementeze (PageLayout) si o implementare pentru un layout de pagina (DoubleBarLayout). Tot codul utilizat in acest tutorial este disponibil pentru download.
Un simplu exemplu
Urmatoarele exemple utilizeaza un array de string-uri. Iata setul de date:
* Andrew
* Bernard
* Castello
* Dennis
* Ernie
* Frank
* Greg
* Henry
* Isac
* Jax
* Kester
* Leonard
* Matthew
* Nigel
* Oscar
Bineinteles, acest cod poate fi extins cu usurinta, pentru a utiliza un array de integeri, caractere sau alte obiecte care au fost obtinute dintr-o baza de date. Iata cum vom folosi clasa Paginated:
<?php
require_once "Paginated.php";
//create an array of names in alphabetic order
$names = array("Andrew", "Bernard", "Castello", "Dennis", "Ernie", Frank", Greg", "Henry", "Isac", "Jax", "Kester", "Leonard", "Matthew", "Nigel", "Oscar");
$pagedResults = new Paginated($names, 10, 1);
echo "<ul>";
while($row = $pagedResults->fetchPagedRow()) {
echo "<li>{$row}</li>";
}
echo "</ul>";
?>
Mai intai includem clasa Paginated si inregistram un array in constructor. Constructorul primeste trei argumente, ultimile doua fiind optionale:
* Primul parametru este array-ul de elemente ce vor fi afisate - acestea pot fi tipuri primitive de date sau obiecte mai complexe
* Al doilea parametru reprezinta numarul de rezultate pe care vrem sa-l afisam in pagina
* Al treilea parametru este numarul paginii curente
In exemplul de mai sus, am folosit constanta 1 pentru a specifica "pagina 1", dar cel mai probabil ca vei dori sa trimiti informatia ca parametru din cererea la baza de date (vom detalia mai tarziu). Daca este furnizat un numar invalid/inexistent de pagina, constructorul va seta 1 ca pagina implicita.
Apeland metoda fetchPagedRow in interiorul buclei, codul nostru itereaza [rin array, tiparind primele 10 nume din lista. Restul ar trebui sa fie incluse in pagina urmatoare, dar, momentan nu exista link catre acea pagina. In timp ce clasa Paginated se va ocupa cu accesul la orice obiect inregistrat de programator, responsabilitatea publicarii rezultatelor ii revine clasei care implementeaza interfata PageLayout.
In continuare, vom adauga cod pentru a afisa numarul de pagini, iar apoi vom studia un pic mai in profuzime felxibilitatea acestei clase.
Creaza un fisier PHP nou, ce contine urmatorul cod:
<?php
require_once "Paginated.php";
require_once "DoubleBarLayout.php";
//create an array of names in alphabetic order
$names = array("Andrew", "Bernard", "Castello", "Dennis", "Ernie", "Frank", "Greg", "Henry", "Isac", "Jax", "Kester", "Leonard", "Matthew", "Nigel", "Oscar");
$page = $_GET['page'];
$pagedResults = new Paginated($names, 10, 1);
echo "<ul>";
while($row = $pagedResults->fetchPagedRow()) {
echo "<li>{$row}</li>";
}
echo "</ul>";
$pagedResults->setLayout(new DoubleBarLayout());
echo $pagedResults->fetchPagedNavigation();
?>
Cand vom rula codul de mai sus, vom vedea o lista a primelor 10 nume, alaturi de informatii aditionale pentru orientare. Scriptul nostru va afisa lista cu nume precum si link-uri pentru navigare intre paginile disponibile (2 in cazul nostru).
In codul de mai sus am folosit o clasa DoubleBarLayout care implementeaza interfata PageLayout si contine implementari ale metodei fetchPagedLinks. Aceasta metoda primeste doi parametri: obiectul Pagination si parametri pe care dorim sa ii atasam, eventual, link-ului.Marele avantaj al acestei metode este ca profita de capabilitatile polimorfismului in PHP, permitand strategiei inregistrate sa fie fie apelata. De aceea este important sa stabilim in primul rand strategia, inainte de a apela metoda. Setarea strategiei este prin intermediul unei apelari a metodei de setare setLayout, care primeste ca parametru un obiect care implementeaza interfata PageLayout.
La o trecere cu mouse-ul peste link vei observa ca parametrul page si valoarea sa, 2, sunt incluse in URL. Totusi, daca faci clik pe acest link, in stadiul actual, pentru a ajunge in pagina a doua, vei observa ca numele care ar trebui sa apara nu apar.
Sa aflam de ce se intampla acest lucru, prin revenirea asupra constructorului Paginated.
Construcotrul primeste trei parametri:
1. array-ul cu variabile primitive sau obiecte, ce urmeaza a fi procesate
2. numarul de rezultate afisate
3. numarul paginii
Pentru ca metoda fetchPagedNavigation scrie o cerere parametru, putem inlocui valoarea 1, scrisa fortat in cod, cu valoarea prezenta in $_GET['page']. In acest fel, daca userul modifica manual valoarea din URL in ceva invalid, Paginated va trece implicit la valoarea 1. Cum alegi sa validezi ce vine in GET depinde numai de tine.
Flexibilitatea in schemele layout-ului paginii
Flexibilitatea acestei clase este realizata prin intermediul interfetei PageLayout, care este parte din obiectul Paginated. Interfata PageLayout poate referentia orice obiect care o implementeaza, si apeleaza metoda fetchPagedNavigation din Paginated, cauzand obiectul curent sa poate fi referentiat. Daca nu ai mai utilizat interfete pana acum, informatiile de aici s-ar putea sa ti se para un pic confuze, dar in principiu, rezultatul final este ca va fi apelat codul corect, iar rezultatele noastre vor fi impartite pe mai multe pagini.
Pentru a implementa aceasta tehnica, tot ce ai nevoie este sa creezi o strategie de layout care sa implementeze interfata PageLayout. Apoi, furnizeaza o implementare pentru metoda fetchPagedLinks.
Aceasta metoda accepta doi parametri:
1. $parent, care este obiectul Paginated
2. $queryVars, care reprezinta lista de parametri ce urmeaza a fi adaugati la numarul paginii (si este optional)
Sunt doua aspecte importante care merita mentionate:
1. Niciodata nu vei apela direct fetchPagedLinks. Toate metodele din Paginated pot fi accesate prin intermediul obiectului parinte.
2. Daca vrei sa folosesti propriile tale layout-uri, trebuie sa schimbi layout-ul resultatului pagina prin apelari ale setLayout.
Cu acestea in minte, sa cream propriul nostru layout de pagina. Il intitulam TrailingLayout. Iata codul:
<?php
class TrailingLayout implements PageLayout {
public function fetchPagedLinks($parent, $queryVars) {
$currentPage = $parent->getPageNumber();
$totalPages = $parent->fetchNumberPages();
$str = "";
if($totalPages >= 1) {
for($i = 1; $i <= $totalPages; $i++) {
$str .= " <a href="?page={$i}$queryVars">Page $i</a>";
$str .= $i != $totalPages ? " | " : "";
}
}
return $str;
}
}
?>
Clasa de mai sus, TrailingLayout, implementeaza interfata PageLayout, si ofera implementare pentru fetchPagedLinks. Adu-ti aminte ca parametrul $parent este o instanta a obiectului Paginated, de aceea putem determina pagina curenta, si totalul paginilor, apeland getPageNumber si respectiv fetchNumberPages.
In acest layout simplu, imediat ce apar mai multe pagini, scriptul va trece prin array-ul de pagini si va crea un link si un numar de pagina pentru fiecare dintre ele. $queryVars este, de asemenea, scris in href ca parte a iteratiei; parametrul $queryVars este util atunci cand paginam rezultatul unei cautari care ar putea include cativa parametri.
Ai in vedere faptul ca stringul "Page" nu face parte din $queryVars, dar este scris de iteratia care ataseaza numerele paginilor.
Sa incercam sa implementam noul layout:
<?php
require_once "Paginated.php";
//include your customized layout
require_once "TrailingLayout.php";
//create an array of names in alphabetic order. A database call could have retrieved these items
$names = array("Andrew", "Bernard", "Castello", "Dennis", "Ernie", "Frank", "Greg", "Henry", "Isac", "Jax", "Kester", "Leonard", "Matthew", "Nigel", "Oscar");
$page = $_GET['page'];
$pagedResults = new Paginated($names, 10, $page);
echo "<ul>";
while($row = $pagedResults->fetchPagedRow()) {
echo "<li>{$row}</li>";
}
echo "</ul>";
//$pagedResults->setLayout(new TrailingLayout());
echo $pagedResults->fetchPagedNavigation("&firstLetter=l");
?>
Daca rulam scriptul de mai sus ca atare, vom primi urmatorul mesaj de eroare: "Fatal error: Call to a member function fetchPagedLinks() on a non-object"
Aceasta eroare apare pentru ca nu am inregistrat strategia pe care dorim sa o folosim inainte de a apela fetchPagedNavigation. Pentru a schimba layout-ul linkurilor de paginatie, transmitem catre metoda setLayout un parametru, care poate fi orice obiect ce implementeaza interfata PageLayout. In codul din exemplul de mai sus, de-comenteaza penultima linie si actualizeaza (refresh) pagina.
Ultima linie din codul de mai sus demonstreaza cum metoda fetchPagedNavigation poate primi un parametru string optional pentru a defini restul cererii (fii atent la & de dinainte de parametrul firstLetter din URL, pentru a-l distinge de parametrul page)
Sumar
In acest articol, am introdus paternul Strategy Design, care poate fi folosit pentru a oferi flexibilitate atunci cand realizezi paginatii.
Am urmarit acest patern pe parcursul clase Paginated, care, sa speram, se va dovedi utila atunci cand afisezi informatii pe mai multe pagini. Clasa poate fi folosita pentru a afisa array-uri ce contin seturi de date primitive sau obiecte mai complexe.
Tutorial adaptat dupa sitepoint.com
O alternativa la metoda prezentata in acest tutorial o reprezinta si Pager din PEAR
punctweb.com nu-si asuma raspunderea pentru eventualele daune provocate de punerea, eventual defectuoasa, in practica a acestui tutorial.
Link-ul autorului:
www.punctweb.com/articole-si-tutoriale/paginare-perfecta-in-php.html
Comentarii
putem forma o pagina web si cu ajutorul php si cu html? care e mai potrivita?
php e server side - adica ruleaza pe server si poate sa scrie html
html - e client side (adica e interpretat de browser)
ideal e sa generezi codul html cu php.
Voteaza acest articol!
Trimite un comentariu!