Paginate function
ik wil een soort van paginate functie maken en toen ik begon leek het niet zo moeilijk maar ik denk dat ik het te moeilijk aan het maken ben.
De bedoeling is dat er 4 knopjes staan: eerste, vorige, volgende, laatste. Dit verwijst naar rapporten die gebonden zijn aan users, iedere user moet dus zijn eigen rapporten zien en niet die van een andere. Hoe kan ik zo eenvoudig mogelijk het eerste id, laatste id volgende en voorgaande id ophalen aan de hand van een userid en een rapport id?
Jasper
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php
$sQuery = "SELECT id FROM rapports WHERE user_id = ".(int) $userId." ORDER BY id";
$result = mysql_query($sQuery, $sqlLink);
if( $result !== false )
{
$ids = array();
while( $row = mysql_fetch_assoc($result) )
{
$ids[] = $row['id'];
}
echo 'Eerste id: '.$ids[0];
echo 'Current id: '.current($ids);
echo 'Vorige id: '.prev($ids);
echo 'Volgende id: '.next(next($ids)); // 2x next omdat we hiervoor 1 terug zijn gegaan
echo 'Laatste id: '.end($ids);
}
else
{
echo 'Error!!! '.mysql_error();
}
?>
$sQuery = "SELECT id FROM rapports WHERE user_id = ".(int) $userId." ORDER BY id";
$result = mysql_query($sQuery, $sqlLink);
if( $result !== false )
{
$ids = array();
while( $row = mysql_fetch_assoc($result) )
{
$ids[] = $row['id'];
}
echo 'Eerste id: '.$ids[0];
echo 'Current id: '.current($ids);
echo 'Vorige id: '.prev($ids);
echo 'Volgende id: '.next(next($ids)); // 2x next omdat we hiervoor 1 terug zijn gegaan
echo 'Laatste id: '.end($ids);
}
else
{
echo 'Error!!! '.mysql_error();
}
?>
En kijk ook eens naar de PHP functies: current, prev, next en end
Gewijzigd op 30/12/2011 16:39:31 door Wouter J
Daarvoor heb je nodig het totaal aantal records in de database dat aan de voorwaarde voldoet (total_records) en de huidige pagina (current).
Totaal aantal records kan je met elke query ophalen met de MySQL functie SQL_CALC_FOUND_ROWS. Huidige pagina moet je elke keer meegeven in een GET parameter van de pagina link. Vervolgens gebruik je die in de LIMIT van je SQL statement om alleen het juiste record op te halen.
De waarde van je pagination buttons worden dan:
eerste: positie = 0;
vorige: positie = max(0, current-1);
volgende: positie = min(current+1, total_records-1);
laatste: positie = total_records-1;
positie zoals boven beschreven gebruik je in de linkjes als de GET parameter voor die pagina.
@Wouter, bedankt ik ga het eens bekijken. Ik heb wel nog één vraagje hoe weten we wat current is? In de url staat natuurlijk id=getal maar ik zie dit nergens terug komen in het script. De bedoeling is natuurlijk als we aan het kijken zijn naar rapport 164 dat de volgende 167 is, de vorige 78 de eerste 5 en de laatste 170.
http://waldio.webatu.com/phphulp/forum/pagination.php?id=25
(voor id kun je ook andere getallen invullen)
Geef een code get variabele mee in de url als je de broncode wilt zien (dus ?code of &code)
@Jasper, ik heb even een voorbeeldje gemaakt, daarop kan je het zien: (voor id kun je ook andere getallen invullen)
Geef een code get variabele mee in de url als je de broncode wilt zien (dus ?code of &code)
Wouter, de link werkt bij mij niet?
PHP Jasper op 31/12/2011 14:03:29:
@Erwin, wouter zijn oplossing kan wel kloppen omdat de id's per user wel oplopend zijn bijvoorbeeld 5, 13, 25, 78, 164, 167, 170, ... Stel nu dan 25 current is dan is de vorige in de array 13 en dus niet 24 zoals jij het bedoel denk ik?
Nee, zoals ik het bedoel gebruik je niet de id's uit je database, maar 'virtuele' id's. Stel je hebt die rij die jij geeft alszijnde de pagina id's van gebruiker x. Dus [5, 13, 25, 78, 164, 167, 170]. Dan zijn de virtuele id's dus [0, 1, 2, 3, 4, 5, 6]. Zit je nu op pagina 4, dan is de volgende 5 en de vorige 3. De eerste is altijd 0, de laatste is 6.
Het SQL statement dat je nodig hebt om het uit de database te halen is:
Code (php)
1
2
3
4
5
2
3
4
5
SELECT SQL_CALC_FOUND_ROW pagina_id, tekst etc etc
FROM tabel_t
WHERE user_id = x
ORDER BY pagina_id
LIMIT 4, 1
FROM tabel_t
WHERE user_id = x
ORDER BY pagina_id
LIMIT 4, 1
Je selecteert dus all pagina's van gebuiker x, maar neem in dit geval alleen de 4e pagina. Verder heb je nog nodig het totaal aantal pagina's wat aan het statement voldoet (in dit geval het totaal aantal pagina's van gebruiker x) en dat wordt berekend door SQL_CALC_FOUND_ROWS. Om het resultaat daarvan te krijgen moet je het SQL statement SELECT FOUND_ROWS()
De pagination parameters kan je dan uitrekenen met de formules dit ik je in mijn vorige post gaf.
Het voordeel van het gebruik van deze methode boven die van Wouter, is dat je dus niet elke keer alle records van gebruiker x uit de database hoeft te trekken (ook al zijn dat alleen maar de id's). Wat als die gebruiker er 1000 heeft? Dan haal je dus 1000 records op om alleen maar 4 waardes te gebruiken. Dat is dus 996 overbodige records.
Het nadeel is dat de link die je creeert om naar een pagina te komen (pagina.php?gebruiker=x&pagina_id=4) een volgende keer misschien niet meer hetzelfde resultaat zal weergeven als er bijvoorbeeld een record is verdwenen uit de database.
@Erwin, ik vind jouw manier ook erg goed maar ik zou graag hebben dat het id van het bericht in de url staat en niet een fictief id.. gaat dit ook?
PHP Jasper op 31/12/2011 15:36:19:
Wouter, de link werkt bij mij niet?
Oh, bij mij wel. Dan maar direct de code:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php if( isset( $_GET['code'] ) ) highlight_file(__FILE__); ?>
<pre>
<?php
$ids = Array(5, 13, 25, 78, 164, 167, 170);
if( !isset($_GET['id']) || !in_array($_GET['id'], $ids) )
{
die('Geef als get variabele id een waarde van '.implode(', ', $ids).' mee');
}
// Dit zorgt ervoor dat we de gegeven id als current benoemen
while (current($ids) !== (int) $_GET['id']) next($ids);
echo 'Eerste id: '.$ids[0].PHP_EOL;
echo 'Current id: '.current($ids).PHP_EOL;
echo 'Vorige id: '.prev($ids).PHP_EOL;
next($ids); // 2x next omdat we hiervoor 1 terug zijn gegaan
echo 'Volgende id: '.next($ids).PHP_EOL;
echo 'Laatste id: '.end($ids).PHP_EOL;
?>
<pre>
<?php
$ids = Array(5, 13, 25, 78, 164, 167, 170);
if( !isset($_GET['id']) || !in_array($_GET['id'], $ids) )
{
die('Geef als get variabele id een waarde van '.implode(', ', $ids).' mee');
}
// Dit zorgt ervoor dat we de gegeven id als current benoemen
while (current($ids) !== (int) $_GET['id']) next($ids);
echo 'Eerste id: '.$ids[0].PHP_EOL;
echo 'Current id: '.current($ids).PHP_EOL;
echo 'Vorige id: '.prev($ids).PHP_EOL;
next($ids); // 2x next omdat we hiervoor 1 terug zijn gegaan
echo 'Volgende id: '.next($ids).PHP_EOL;
echo 'Laatste id: '.end($ids).PHP_EOL;
?>
PHP Jasper op 01/01/2012 14:44:26:
@Erwin, ik vind jouw manier ook erg goed maar ik zou graag hebben dat het id van het bericht in de url staat en niet een fictief id.. gaat dit ook?
Waarom zou je dat willen? Geen gebruiker die daar iets aan heeft als je het mij vraagt. Als je het zou doen krijg je alleen maar meer SQL queries die je moet gaan draaien om iets te krijgen dat niet nodig is. Minder efficient dus.
@Erwin, en hoe bepaal ik in jouw voorbeeld die 4? Want deze moet telkens anders zijn veronderstel ik?
PHP Jasper op 04/01/2012 14:30:27:
@wouter, ik krijg telkens deze error: Fatal error: Maximum execution time of 30 seconds exceeded in C:\xampp\htdocs\alfaflex\inc\functies.php on line 920
Hier doet ie het. Alleen bij 5 is ie niet correct.
Misschien ligt het aan het aantal records? Er steken er nu 700 in de db..
PHP Jasper op 04/01/2012 14:30:27:
@Erwin, en hoe bepaal ik in jouw voorbeeld die 4? Want deze moet telkens anders zijn veronderstel ik?
Welke 4?
LIMIT 4, 1
Die 4 is de pagina (beginnend bij 0). Die bepaal je dus in de pagination buttons met de functies die ik een tijdje terug gaf en plaats je in de link als een GET parameter.
Als ik in jouw script die while weglaat voor current id lukt het wel maar dan kloppen de gegevens niet. Het huidige id is 167 en dan krijg ik dit als uitkomst: "Eerste id: 630 Current id: 630 Vorige id: Volgende id: Laatste id: 802"
Erwin ik begrijp dus nog steeds niet hoe ik de 4 bepaal. We zitten dus op een pagina: pagina.php?id=168 . 168 is dus het id van dat rapport en aan de hand van dat id halen we het volledige rapport op. Nu komen er boven dat rapport 4 linkjes: "eerste", "Vorige", "volgende", "Laatste". Hoe bepaal ik aan de hand van jouw idee die linkjes? Volgens mij gaat dat ook niet werken.
Toevoeging op 07/01/2012 13:10:48:
@wouter,
deze regel is de boosdoener: "while (current($ids) !== (int) $_GET['id']) next($ids);" hij loopt blijkbaar vast op 800 rows.
Gewijzigd op 07/01/2012 13:03:40 door Jasper DS
Stel je zit op een soort overzicht pagina waarin je een link hebt naar het eerste rapport van gebruiker x. De link die je daar dan maakt moet iets zijn als "rapport.php?user=x&pagina_id=0". Omdat je met virtuele ids werkt is de eerste dus altijd 0!!
Klik je nu op die link dan ga je naar de rapport pagina en je SQL statement krijgt een "LIMIT 0,1" clause. Die 0 is dus de pagina_id.
Vanuit die 0 kan je de eerste, vorige, volgende en laatste berekenen:
Eerste = 0
vorige = 0
volgende = max(huidige pagina +1, totaal aantal records -1)
laatste = totaal aantal records - 1
Klik je dan op de volgende krijg je dus een link als "rapport.php?user=x&pagina_id=1". in je SQL krijg je nu een "LIMIT 1,1". Je zit nu dus op pagina 1, maar je rapport id in je database kan nu best al 334 zijn. Je pagination parameters worden nu:
eerste = 0
vorige = min(0, huidige pagina - 1)
volgende = max(huidige pagina + 1, totaal aantal records -1)
laatste = totaal aantal records - 1
Enz enz enz. Begint het al duidelijker te worden?
Ja erwin, ik begrijp het. Dat wil dus zeggen dat ik de pagina waar ik de links genereer ook moet aanpassen en idpv het id in de link te zetten het virtuele id in de link zetten.
Precies. Dat id dat in je database staat heeft verder geen betekenis (in deze methode dan).
Ik probeerde al SQL_CALC_FOUND_ROWS id AS tel maar dat leverde een 1 op. (klopt dus niet) Hoe laat ik dat nog werken?