Zoltan Hosszu

PHP lapozás

Posted on May 4, 2009 by Zoltan - 18 Comments

Ebben a cikkben egy adatbázist fogunk lapozható formára bontani. Nagyon hasznos ez a funkció, főleg egy nagyobb MySQL adatbázisnál, amikor az embernek többszáz recordja van egy táblában és ezeket szeretné a felhasználóknak valami átlátható formában megjeleníteni. Igazság szerint az alább leírt lapokra bontás talán a legegyszerűbb megoldása ennek a funkciónak, de remélem, hasznos lesz számotokra. Az alább összefoglalt függvényt az AlbérletPlusz.hu oldalhoz készítettem, ahol jelenleg is ez a PHP szkript felelős az oldalakra bontásért. Kezdjünk is hozzá.

Először is vegyük gyorsan sorra, hogy mire van szüksége az embernek egy lapozhatóan megjelenő tartalomhoz: honnan kezdődjön a lekérdezés a MySQL táblából és meddig tartson. Igazából a legnehezebb dolog itt nem a táblából való lekérdezés, hiszen azt egy sima “SELECT * FROM tabla LIMIT x, y” paranccsal megoldhatjuk, ahol x az eltolás mértéke (tehát, hogy honnan kezdjük az adatok lekérdezését), y pedig a megjelenítendő elemek száma (hmm, milyen érdekes, pont ezekre van szükségünk egy jól működő lapozás funkcióhoz, micsoda szerencse); a bonyolult funkció a lapok számának dinamikus kiírása, mondjuk egy ilyesmi formában:

lapozas

 

Ezt fogjuk most megírni.

Létrehozunk egy új függvényt mondjuk lapozas néven, és paramétereknek megadjuk az eltolás mértékét és a megjelenítendő elemek számát. A paramétereknek megadunk egy alap értéket, hogy ha a meghíváskor nem kap a függvény értékeket, akkor is tudjon szépen dolgozni.

Szükségünk lesz néhány változóra is: előző oldal, aktuális oldal, következő oldal, az oldalak száma, az oldalakon megjelenítendő összes elem száma, valamint egy olyan változóra ami az aktuális oldalszámtól jobbra és balra kiszámítja, hogy hány oldalt mutassunk: egy intervallumhatárra. Ez utóbbi változót így leírva lehet kicsit nehéz megérteni, de ahogy haladunk látni fogjátok a funkcióját.

function lapozas($offset = 0, $show = 12) { //Lapozás függvény - $offset az eltolás értéke, $show a megjelenítendő elemek száma

	global $osszes; //Itt megkapjuk az összes elem számát a táblából, ezt a lekérdezéskor kell kiszámolnunk.

	$elozo = $offset - $show; //Előző oldal kiszámítása
	$kovetkezo = $offset + $show; //Következő oldal kiszámítása
	$aktoldal = (int)($offset / $show) + 1; //Aktuális oldal
	$oldalszam = $osszes / $show; //Oldalak számának kiszámítása

	if ($oldalszam > (int)($osszes / $show)) $oldalszam = (int)($osszes / $show) + 1; //Oldalszám kerekítése

A változóknak kiszámoljuk a kezdeti értékeit és ezzel meg is van az egyik lényeges adat: a kezdeti értékek. Ezekre nagy szükségünk lesz a következő lépéseknél, hiszen elég sokat fogunk számolni velük. Létrehozunk egy rendezetlen listát (<ul>), az oldalszámokat pedig ebbe fogjuk pakolgatni, majd betesszük első elemnek az “előző oldal” kiírást és linket.

	if ($oldalszam > 1) { //Ha van elég oldal, hogy megjelenítsük

		print('<ul class="scroll">'); //Rendezetlen lista létrehozása, ebben tároljuk az oldalszámokat

		if ($elozo >= 0) print('<li><a href="oldal.php?&offset=' . $elozo .'">« elõzõ oldal</a></li>'); //Előző oldal kiírása, ha nem az első oldalon vagyunk

Innentől két részre bontottam a függvényt, először is azért, mert szerintem 10 oldal alatt nem érdemes a …-os részt belerakni, mert 10-12 link még bőven kifér és átlátható; 10 felett viszont már a $range értékkel is számolgatunk majd.

Szóval 10 oldal alatt egy sima for ciklussal bedobáljuk az oldalszámokat a megfelelő linkekkel a listába. Egy kis finomság: az aktuális oldalt vastaggal fogjuk írni.

		if ($oldalszam < 10) { //Oldalszámozás, ... nélkül

			for ($i = 0; $i < $oldalszam; $i++) {
				$off = ($i * $show) + ($offset % $show); //Offset számítása
				$oldal = $i + 1; //Kiirandó oldalszám megadása

				if ($off == $offset) $oldal = "" . $oldal . ""; //Aktuális oldal vastagon írva

				print ('<li><a href="oldal.php?&offset=' . $off . '">' . $oldal . '</a></li>'); //Kiiratás
			}

		}

Ezzel meg is volnánk, most jön az érdekes rész, a …-ozás ha sok oldal van. Itt már szükségünk lesz a $range értékre, ami a már fent említett intervallumhatár értéket fogja tárolni. Ezt én 2-re állítottam, mert szerintem elég egy ötös (2 balra + aktuális oldal + 2 jobbra) intervallumot látni, de ezt nyugodtan megváltoztathatjátok. Itt be fogunk hozni 2 új változót, egy $start és egy $end változót, amik az aktuális oldaltól számolják a $range értékkel csökkentett ill. növelt értékeket. Ez azért kell, hogy ha az utolsó előtti oldalon vagyunk, ne írjunk ki utolsó+1 oldalt, a második oldalon meg -1-t. :) Lássuk akkor a kódot részletekben.

		 else { //Oldalszámozás ...-tal

			$range = 2; //Intervallum két szélének távolsága aktuális oldaltól

			if ($aktoldal >= ($range *2)) { //Ha messzebb vagyunk az első oldaltól mint $range * 2, kiírjuk az első oldal linkjét
				print ('<li><a href="oldal.php?offset=0">1</a></li>');
			}

			if ($aktoldal > ($range *2)) { //Ha már a második oldal száma nem látszik, kipontozzuk
				print('<li>...</li>');
			}

			$start = $aktoldal - $range; //$start és $end kezdeti értékek
			$end = $aktoldal + $range;

			// /!\ Kritikus rész /!\ a $start és $end pontos kiszámítása

			if ($start < 1) { //Nem megyünk negatívaba, ha közel vagyunk az oldalak elejéhez
				$start = 1;
				$end = ($range * 2) + 1;
			} elseif ($end > $oldalszam) { //Nem megyünk túl a maximális oldalakon, ha a végén vagyunk
				$start = ($oldalszam - ($range * 2) + 1);
				$end = $oldalszam;
			}

Innentől igazából a nehezén túl is vagyunk, most egy sima for-ral ki kell iratnunk az oldalakat, majdnem úgy mint a kipontozós résznél, annyi eltéréssel, hogy most $start-tól $end-ig tesszük ezt meg.

			for ($i = $start; $i <= $end; $i++) { //Oldalak kiírása $start-tól $end-ig

				$off = ($i - 1) * $show;
				$oldal = $i;

				if ($off == $offset) $oldal = "<b>" . $oldal . "</b>";

				print ('<li><a href="oldal.php?offset=' . $off . '">' . $oldal . '</a></li>'); //Kiiratás
			}

Már majdnem készen is vagyunk, egy nagyon apró dolog van csak hátra, az utolsó ill. a következő oldal linkjének kiírása, majd a lista és a függvény lezárása.

			if ($aktoldal < ($oldalszam - ($range * 2) + 1)) {
				print('<li>...</li>');
			}
			if ($aktoldal <= ($oldalszam - ($range * 2) + 1)) {
				$utolso = $osszes - ($osszes % $show);
				print ('<li><a href="oldal.php?offset=' . $utolso . '">' . $oldalszam . '</a></li>'); //Utolsó oldal kiiratása
			}
		}

		if ($kovetkezo <= $osszes ) print('<li style="border: 0px"><a href="' . $klink . '&offset=' . $kovetkezo . '">következő oldal »</a></li>');

		print ("</ul>");
	}

}

Ezzel kész is! Nézzük meg egyben gyorsan:

function lapozas($offset = 0, $show = 12) { //Lapozás függvény - $offset az eltolás értéke, $show a megjelenítendő elemek száma

	global $osszes; //Itt megkapjuk az összes elem számát a táblából, ezt a lekérdezéskor kell kiszámolnunk.

	$elozo = $offset - $show; //Előző oldal kiszámítása
	$kovetkezo = $offset + $show; //Következő oldal kiszámítása
	$aktoldal = (int)($offset / $show) + 1; //Aktuális oldal
	$oldalszam = $osszes / $show; //Oldalak számának kiszámítása

	if ($oldalszam > (int)($osszes / $show)) $oldalszam = (int)($osszes / $show) + 1; //Oldalszám kerekítése

	if ($oldalszam > 1) { //Ha van elég oldal, hogy megjelenítsük

		print('<ul class="scroll">'); //Rendezetlen lista létrehozása, ebben tároljuk az oldalszámokat

		if ($elozo >= 0) print('<li><a href="oldal.php?&offset=' . $elozo .'">« előző oldal</a></li>'); //Előző oldal kiírása, ha nem az első oldalon vagyunk

		if ($oldalszam < 10) { //Oldalszámozás, ... nélkül

			for ($i = 0; $i < $oldalszam; $i++) {
				$off = ($i * $show) + ($offset % $show); //Offset számítása
				$oldal = $i + 1; //Kiirandó oldalszám megadása

				if ($off == $offset) $oldal = "<b>" . $oldal . "</b>"; //Aktuális oldal vastagon írva

				print ('<li><a href="oldal.php?&offset=' . $off . '">' . $oldal . '</a></li>'); //Kiiratás
			}

		} else { //Oldalszámozás ...-tal

			$range = 2; //Intervallum két szélének távolsága aktuális oldaltól

			if ($aktoldal >= ($range *2)) { //Ha messzebb vagyunk az első oldaltól mint $range * 2, kiírjuk az első oldal linkjét
				print ('<li><a href="oldal.php?offset=0">1</a></li>');
			}

			if ($aktoldal > ($range *2)) { //Ha már a második oldal száma nem látszik, kipontozzuk
				print('<li>...</li>');
			}

			$start = $aktoldal - $range; //$start és $end kezdeti értékek
			$end = $aktoldal + $range;

			// /!\ Kritikus rész /!\ a $start és $end pontos kiszámítása

			if ($start < 1) { //Nem megyünk negatívaba, ha közel vagyunk az oldalak elejéhez
				$start = 1;
				$end = ($range * 2) + 1;
			} elseif ($end > $oldalszam) { //Nem megyünk túl a maximális oldalakon, ha a végén vagyunk
				$start = ($oldalszam - ($range * 2) + 1);
				$end = $oldalszam;
			}

			for ($i = $start; $i <= $end; $i++) { //Oldalak kiírása $start-tól $end-ig

				$off = ($i - 1) * $show;
				$oldal = $i;

				if ($off == $offset) $oldal = "<b>" . $oldal . "</b>";

				print ('<li><a href="oldal.php?offset=' . $off . '">' . $oldal . '</a></li>'); //Kiiratás
			}

			if ($aktoldal < ($oldalszam - ($range * 2) + 1)) {
				print('<li>...</li>');
			}
			if ($aktoldal <= ($oldalszam - ($range * 2) + 1)) {
				$utolso = $osszes - ($osszes % $show);
				print ('<li><a href="' . $klink . '&offset=' . $utolso . '">' . $oldalszam . '</a></li>'); //Utolsó oldal kiiratása
			}
		}

		if ($kovetkezo <= $osszes ) print('<li style="border: 0px"><a href="' . $klink . '&offset=' . $kovetkezo . '">következő oldal »</a></li>');

		print ("</ul>");
	}

}

Remélem megértettétek, hogyan is működik ez a függvény, ha nem, bátran kérdezzetek a hozzászólásoknál!

Comments

Toti
May 7, 2009 10:00 pm Reply

Én nem értem :D

    Zoltan
    May 7, 2009 11:28 pm Reply

    Akkor még szerencse, hogy ebből élsz.. :D Amúgy meg megijeszted itt a jónépet! :)

efraim
December 12, 2009 9:02 am Reply

Kipróbáltam volna egy új oldalamon, ami egy magyar-héber-angol szótár és jó lett volna ez a megoldás az update.php -hoz de sajnos

Parse error: parse error in C:\wamp\www\dictionary\admin\paginate.php on line 6

hibát ír.

Csak annyit változtattam, hogy az eredeti 12 sort 25-re növeltem

function lapozas($offset = 0, $show = 25) { //Lapozás függvény – $offset az eltolás értéke, $show a megjelenítendő elemek száma

    Zoltan
    December 12, 2009 12:46 pm Reply

    Így próbáld meg az elejét, szedd ki a var-okat mindenhonnan.

    $elozo = $offset – $show;
    $kovetkezo = $offset + $show; //Következő oldal kiszámítása
    $aktoldal = (int)($offset / $show) + 1; //Aktuális oldal
    $oldalszam = $osszes / $show; //Oldalak számának kiszámítása

B3N
January 16, 2010 9:13 am Reply

Hali!

Pontosan mysql cuccot hogy adjam meg?

Köszi előre is!

    Zoltan
    January 19, 2010 8:21 pm Reply

    Szia

    Így mennie kéne:

    $lekerdezes = “SELECT * FROM tabla ORDER BY id DESC LIMIT ” . $offset . “, ” . $show; //$offset és $show közti eredmények kiválasztása

B3N
January 20, 2010 5:42 pm Reply

Hali!

Próbáltam már sok féle képpen, de semmi nem jött össze mindig egy fehér oldal jön be,semmi hibával.. :S

Pedig van a mysql be adat, és van kapcslat is.

    Zoltan
    January 20, 2010 6:08 pm Reply

    Hát akkor jöjjön a debug, próbáld kikommentelni bizonyos részeket, printtel tesztelni a változók értékeit és akkor meglesz a hiba :) A forrásnak elvileg jónak kéne lennie

B3N
January 20, 2010 5:43 pm Reply

kapcsolat*

Viki
February 12, 2010 4:35 pm Reply

Nekem hibát ír ki.

(Warning: mysql_num_rows(): supplied argument is not a valid MySQL result resource in D:\-=Weblapok\oldal.php on line 121
Warning: mysql_fetch_assoc(): supplied argument is not a valid MySQL result resource in D:\-=Weblapok\oldal.php on line 122)

A kódon semmit nem változtattam.
A hiba itt van valahol:

$lekerdez = mysql_query(“SELECT * FROM vendegkonyv ORDER BY id DESC LIMIT” . $offset . “, ” . $show); //$offset és $show közti eredmények kiválasztása
$osszes= mysql_num_rows($lekerdez); //LEKÉRDEZÜK A SOROK SZÁMÁT
while( $sor = mysql_fetch_assoc( $lekerdez ) )
{
echo $sor['username'];echo”";
}

    Zoltan
    February 12, 2010 5:20 pm Reply

    Szerintem a hiba ott lesz, hogy a LIMIT után nincs szóköz. Próbáld meg anélkül és szólj ha nem megy :)

      Viki
      February 12, 2010 7:35 pm

      Köszi a gyors választ. Kipróbáltam úgy is, és nem jött össze. Ugyan az a hiba.

      A komplett kód igy néz ki nálam:

      (int)($osszes / $show)) $oldalszam = (int)($osszes / $show) + 1; //Oldalszám kerekítése

      if ($oldalszam > 1) { //Ha van elég oldal, hogy megjelenítsük

      print(”); //Rendezetlen lista létrehozása, ebben tároljuk az oldalszámokat

      if ($elozo >= 0) print(‘« előző oldal‘); //Előző oldal kiírása, ha nem az első oldalon vagyunk

      if ($oldalszam < 10) { //Oldalszámozás, … nélkül

      for ($i = 0; $i < $oldalszam; $i++) {
      $off = ($i * $show) + ($offset % $show); //Offset számítása
      $oldal = $i + 1; //Kiirandó oldalszám megadása

      if ($off == $offset) $oldal = "” . $oldal . ““; //Aktuális oldal vastagon írva

      print (‘‘ . $oldal . ‘‘); //Kiiratás
      }

      } else { //Oldalszámozás …-tal

      $range = 2; //Intervallum két szélének távolsága aktuális oldaltól

      if ($aktoldal >= ($range *2)) { //Ha messzebb vagyunk az első oldaltól mint $range * 2, kiírjuk az első oldal linkjét
      print (‘1‘);
      }

      if ($aktoldal > ($range *2)) { //Ha már a második oldal száma nem látszik, kipontozzuk
      print(‘…’);
      }

      $start = $aktoldal – $range; //$start és $end kezdeti értékek
      $end = $aktoldal + $range;

      // /!\ Kritikus rész /!\ a $start és $end pontos kiszámítása

      if ($start $oldalszam) { //Nem megyünk túl a maximális oldalakon, ha a végén vagyunk
      $start = ($oldalszam – ($range * 2) + 1);
      $end = $oldalszam;
      }

      for ($i = $start; $i <= $end; $i++) { //Oldalak kiírása $start-tól $end-ig

      $off = ($i – 1) * $show;
      $oldal = $i;

      if ($off == $offset) $oldal = "” . $oldal . ““;

      print (‘‘ . $oldal . ‘‘); //Kiiratás
      }

      if ($aktoldal < ($oldalszam – ($range * 2) + 1)) {
      print('…’);
      }
      if ($aktoldal <= ($oldalszam – ($range * 2) + 1)) {
      $utolso = $osszes – ($osszes % $show);
      print ('‘ . $oldalszam . ‘‘); //Utolsó oldal kiiratása
      }
      }

      if ($kovetkezo <= $osszes ) print('következő oldal »‘);

      print (“”);
      }

      }
      ?>

      <?php

      $lekerdez = mysql_query("SELECT * FROM vendegkonyv ORDER BY id DESC LIMIT". $offset . ", " . $show); //$offset és $show közti eredmények kiválasztása
      $osszes= mysql_num_rows($lekerdez); //LEKÉRDEZÜK A SOROK SZÁMÁT
      while( $sor = mysql_fetch_assoc( $lekerdez ) )
      {
      echo $sor['username'];echo"”;
      }
      ?>

Viki
February 12, 2010 7:38 pm Reply

Látom most is.
igazából a te kódod előtt csak a sql csatlakozás van.

Crystal
May 1, 2010 8:13 pm Reply
    Zoltan
    May 1, 2010 8:19 pm Reply

    :)

    Régi projekt, nem értettem még hozzá :)

Hlaci
June 27, 2010 1:09 pm Reply

Hi!
Nekem egy vendégkönyvhöz kellett, ahol ugye mindíg az utolsó hozzászólások jönnek be először, úgyhogy megfordítottam a cuccot, és tökéletesen műxik! Köszönöm szépen! Üdv! Laci

dlaczko
July 1, 2010 2:35 pm Reply

Szia, leírnád kérlek pontosan hová kell rakni a mysql lekérdezést és aztán annak kiíratását, hogy működjön? Mert már lassan mindenhová tettem de mégsem működik. Köszi!

Roller232
November 11, 2010 5:56 pm Reply

Egy ötelt! Ha van egy tutorial-od tedd letölthetővé, sokkal egyszerűbb megérteni is talán!

Leave a Reply

Your email address will not be published. Required fields are marked *

Name *:
E-mail address *:
Website:
Message:
You may use these: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>