Newsgroup: it.comp.www.php
Titolo: paginazione php e mysql

Ciao...vorrei gestire le news sul mio sito tramite la paginazione del
risultato della query....
Da quello che ho visto basta usare la funzione sql LIMIT
Da qualche parte ho letto che, se uso la clausola order by sulla query
(che è il mio caso...ordinate dalla più recente alla più vecchia)
quello che succede è che mysql cmq restituisce tutti i record, perchè
deve ordinarli, e poi esegue la LIMIT. Quindi quello che succede è che
in pratica è come fare una select a tappeto su tutta la tabella. Nel
mio caso...avendo pochi record...non c'è problema....ma con grossi
volumi di dati non è un grosso spreco?
Esiste un modo per ovviare al problema?
Grazie
Ciao

 e non fare 2 query per spaginare (non hai il numero delle pagine)
ehm....che intendi esattamente per spaginare?
Quello che voglio fare è eseguire la query con limiti diversi su ogni
pagina che devo visualizzare
grazie ancora

 > > e non fare 2 query per spaginare (non hai il numero delle pagine)
ho capito ora che intendevi...appena ci ho sbattuto il muso....se
faccio in ogni pagina la query con la limit....non so quante pagine ho
in totale....
ma allora come posso fare per evitare di fare un'altra query iniziale
per deteminare il n. totale di pagine?
grazie

 per deteminare il n. totale di pagine?
Hai due possibilita`:
(quella pesante): Fai la query senza limit, carichi tutto in un array, poi 
leggi l'array dalla posizione voluta
(quella leggera, un po' piu` complicata): Fai la query senza limit, poi 
usi mysql_seek per andare alla riga che ti interessa, e leggi le righe che 
ti servono.
In entrambi i casi puoi usare mysql_num_rows per sapere quanti risultati 
ci sono.
Bye.


il mio fa schifo sicuramente ma te lo posto (se qualcuno mi
corregge...prendilo per stra.buono):
faccio una funzione pager che mi crea la paginazione a link:
------------------------
function pager($pages, $cpage) {
  $u = "";
  for ($i=0; $i<$pages; $i++) {
    $p = $i+1;
    if ($cpage == $p) {
      $u .= "&nbsp;<b>$p</b>&nbsp;";
    } else {
      $u .= "&nbsp;<a href='?p=$p' title='Go to page $p'>$p</
a>&nbsp;";
    }
  }
  return $u;
}
-----------------
definisco quanti record voglio per pagina
$recperpage = 30; //Che sarebbe il secondo valore di LIMIT
verifico il valore in querystring del numero pagina corrente (di
solito uso GET)
$curpage = isset($_GET["page"]) ? $_GET["page"] : 1;
faccio la query senza limit, creo un recordset e lo conto, poi chiudo
il recordset , creo il limit e lo aggiungo alla query:
$sql = "select * from tabella ";
$rst = mysql_query($sql);
$cnt = mysql_num_rows($rst);
if ($cnt > $recperpage) {
  $pages = ceil($cnt / $recperpage);
  if ($curpage == 1) {
    $lsize = 0;
  } else {
    $lsize = ($recperpage * $curpage)-$recperpage;
  }
  $limit = "LIMIT $pages, $recperpage";
} else {
  $pages = 1;
  $limit = "LIMIT 0, $recperpage";
}
$sql .= " $limit ";
$rst = mysql_query($sql);
..qui ho il risultato paginato in base alla pagina selezionata...
per fare il pager con i link uso <?php echo pager($recperpage,
$curpage) ?>
chiaramente non ho fatto debug.
SICURAMENTE fa schifo il mio modo, quindi se qualcuno lo puo'
correggere in meglio grazie.
Inoltre sul forum di 
html.it
 alla sezione PHP c'e' un utente guidoz
che nel suo sito (cercalo) ha fatto una bella funzioncina che pare
funzionare a meraviglia.
Il link:
http://www.guidoz.it/forum/viewtopic.php?t=451
ciao :)

 Bye.
Io farei così. Diciamo che hai una tabella "news" con 4 campi: "id", 
"data", "titolo", "contenuto". Id è la chiave primaria, data è un 
timestamp, titolo e contenuto sono testo. L'idea generale è questa:
// connessione al db
$con = mysql_connect(...);
// ottiene il numero totale di news
$res = mysql_query("SELECT COUNT(id) AS tot FROM news", $con)
$row = mysql_fetch_assoc($res);
$tot = $row['tot'];
mysql_free_result($res);
// configura lo script
define("PER_PAGE", 10); // numero di righe per pagina
define("CUR_PAGE", $_GET['page']); // pagina corrente (0, 1, 2, n)
define("TOT_PAGE", ceil($tot / PER_PAGE)); // numero di pagine
// esegue la query
$res = mysql_query("SELECT data, titolo, contenuto FROM news ORDER BY 
data ASC LIMIT " . CUR_PAGE * PER_PAGE . ", " . PER_PAGE, $con);
while($row = mysql_fetch_assoc($res)
{
	... // stampa la notizia
}
mysql_free_result($res);
// stampa l'indice delle pagine
for($i = 0; $i < TOT_PAGE; $i++)
{
	if ($i != $CUR_PAGE)
		print("<a href=\"?page={$i}\">{$i}</a>&nbsp;");
	else print($i . "&nbsp;");
}
// chiude la connessione
mysql_close($con);
Ovviamente è solo uno scheletro, devi completarlo, correggerlo, 
aggiungere i debiti controlli di sicurezza etc.
Guardati anche la doc sulla funzione sql COUNT() 
(
http://dev.mysql.com/doc/refman/5.0/en/counting-rows.html
)
Buon lavoro

 $res = mysql_query("SELECT COUNT(id) AS tot FROM news", $con)
Come mai non useresti direttamente mysql_num_rows ?
-- 
Jax

 data ASC LIMIT " . CUR_PAGE * PER_PAGE . ", " . PER_PAGE, $con);
Si` ma:
1- La domanda era come farlo con una sola query, tu ne fai due. 
2- Fare due query e` comunque molto pesante, perche` il DB le deve 
compilare
3- Nella seconda query, il DB calcolera` comunque tutte le righe, e poi 
estrarra` quelle che ti servono con limit, quindi avrai comunque la stessa 
occupazione di memoria e di CPU che calcolarle tutte.
4- Se il tuo DB non e` locale devi effettuare due trasferimenti via TCP/IP 
invece di uno solo, e il primo e` abbastanza piccolo da non ingrandire la 
finestra del TCP, quindi il secondo probabilmente iniziera` molto lento 
per poi accelerare.
5- Finche` hai una query cosi` ti va anche bene, ma pensa a qualcosa del 
genere:
select 
a.name
, a.email, p.title, p.content, 
c.name
 from author a, post p, 
category c where a.uid=p.uid and p.cid=c.cid and (
c.name
='PHP' or 
c.name
='SQL');
Qui hai una join di tre tabelle, probabilmente bella pesantina in un CMS.
E la fai due volte, una coi campi richiesti, una col count.
Pensa se dovessi calcolare anche quanti commenti ha ricevuto ogni post.
Memorizzare tutti i risultati come dicevo io e` sicuramente piu` leggero 
che fare questa query due volte.
Oh, non dico che sia sbagliato quello che hai detto, eh? :)
Solo che va valutato caso per caso quale sia il modo migliore.
Sicuramente in un DB locale con una tabella semplice senza join e where il 
tuo metodo e` ottimo.
Bye.


Faccio anche io in maniera simile, ma con una variante: uso l'offset con 
il limit e lo faccio calcolare da una funzione apposita tramite il 
passaggio della variabile $page (la pagina attuale)... E uso il 
founds_rows di mysql (in seguito alla query con SELECT 
SQL_CALC_FOUND_ROWS...) per sapere già quante pagine saranno...
Saluti a tutti,
Davidecat


Ok...mi sono assentato qualche giorno e la discussione è diventata
molto interessante....ringrazio tutti per i consigli....ora devo
valutare bene quale metodo mi conviene usare...
vi faccio sapere