Ierakstu dalīšana pa lappusēm

24
Jan
21

Tēma šoreiz nav sareģīta, bet visur ir savs āķis.

Zināms, ka, lai izrēķinātu lappušu skaitu, jāzin kopējais ierakstu skaits, tātad divi pieprasījumi uz datubāzi:

  1. Iegūstam nepieciešamo skaitu ar ierakstiem
  2. Iegūstam kopējo ierakstu skaitu

Bet kur tad optimizācija? Un ja vēl nepieciešams liels skaits dinamiski ģenerētu filtru? Būs jāveido divi gandrīz identiski pieprasījumi – viens ar limitu, viens bez.

Es piedāvāju izmantot vienu no ne tik slavenajām MySQL funkcijām – SQL_CALC_FOUND_ROWS un FOUND_ROWS(). Pieprasījums un tā apstrāde, manā gadījumā, izskatīsies šādi:

1
2
3
4
5
6
7
8
9
10
11
12
<?
  $perpage=10; // ieraksti vienā lappusē
  $_LIMIT=(!empty($_GET['p']) && $_GET['p']>1)?($_GET['p']*$perpage)-$perpage:0; // izrēķinam limita sākuma pozīciju, atkarīgā no atvērtās lappuses, kas padota kā ?p=X
  $_LIMIT.=", ".$perpage;
  $sql="SELECT SQL_CALC_FOUND_ROWS * FROM `tabula` LIMIT ".$_LIMIT;
  $res=mysql_query($sql);
  $count=mysql_fetch_object(mysql_query("SELECT FOUND_ROWS() as c"));
  while($row=mysql_fetch_object($res)){
    var_dump($row);
  }
  $pages=splittopages($count->c,$perpage);
?>

Funkcija, kura izrēķinās lappušu skaitu. Pieejamās lappuses tiek saliktas masīvā, lai būtu vienkāršāk izveidot pogas “Nākamā lappuse” un “Iepriekšējā lappuse” – atliek tikai pārbaudīt vai masīvā eksistē ieraksts ar atbilstošu atslēgu.

1
2
3
4
5
6
7
8
9
10
11
<?
  function splittopages($count,$perpage){
    $pagescount=ceil($count/$perpage);
      $pages=array();
      if($pagescount<2){ return $pages; }
        for($i=1;$i<=$pagescount;$i++){
        $pages[]=$i;
      }
    return $pages;
  }
?>

Lappušu izvade.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  if($_GET['p']<2){ $_GET['p']=1; } // definēsim lappusi paši, ja tā vēl nav definēta
  $now=array_search($_GET['p'],$pages); // atvērtā lappuse
  $prev=$now-1;
  $next=$now+1;
  if(array_key_exists($prev,$pages)){
    echo '<a href="?p='.$pages[$prev].'">Iepriekšējā lappuse</a>';
  }
  foreach($pages as $value){
    $active=$_GET['p']==$value?' class="active"':''; // atzīmējam atvērto lappusi
    echo '<a href="?p='.$value.'"'.$active.'>'.$value.'</a>';
  }
  if(array_key_exists($next,$pages)){
    echo '<a href="?p='.$pages[$next].'">Nākamā lappuse</a>';
  }
?>

Lielākais ieguvums izmantojot šādu risinājumu ir tāds, ka nav jāsūta vēl viens praktiski identisks pieprasījums uz datubāzi, ierakstu skaits jau tiek nokešots MySQL’ā.
Bez liekiem if’iem tiek pie nākamās un iepriekšējās lappuses.

Filed under: PHP, datubāzes
21 Comments

21 Comments

  1. kaac
    21:39 on January 30th, 2009

    Attiecībā uz SQL_CALC_FOUND_ROWS, šeit http://laacz.lv/2007/10/19/muzu-dzivo-muzu-macies/ jau komentāros aprunāts, ka ne vienmēr tas būs tas optimālākais variants.

  2. Mārcis
    14:41 on February 1st, 2009

    Beigu beigās taču tika atzīts, ka šis strādā ātrāk par diviem selektiem, vai ne?

  3. duplets
    23:25 on February 6th, 2009

    $count=mysql_fetch_object(mysql_query(”SELECT FOUND_ROWS() as c”));
    Šito rindiņu pavisam noteikti var aizvietot ar kko šādu:
    $count=mysql_num_rows($res);
    Bet tā visā visumā man ar šito kodu sanāca ātrāk, paldies!

  4. Mārcis
    23:51 on February 6th, 2009

    @duplets
    Tā gan nevarēs, jo FOUND_ROWS() atgriež vienu ciparu, nevis ierakstu kaudzīti. mysql_num_rows() saskaita, cik ieraksti atgriezti.

  5. duplets
    23:57 on February 6th, 2009

    uij, nē, bik sapinos meistarība, nemaz neiedziļinājos, ko tas tavs nodefinētais $count strings dara, mysql_num_rows nederēs… (BLUSH)

  6. wuu
    12:13 on February 7th, 2009

    Eu itka man vis sanaca bet ka var uztaisit lai skripts paslep liekas lapas? jo man vinas loti daudz un tad tas lapu links ir izkroplots, ka noslept un tad taka lielaka dala laposanas skriptos uzradit pa lapai?
    cerams ka sapratat manu domu!

  7. Mārcis
    14:44 on February 7th, 2009

    Tak pakustini smadzenes, ciklā, kurā izvadi lapu linkus, nepieciešams viens vai divi if’i (pēc izvēles).
    Ja konkrētās lapas numurs ir lielāks par, piemēram, 3 un mazāks par pēdējā lapa -3, tad šo izlaižam (iesaku lietot “continue;”).

  8. wuu
    14:51 on February 7th, 2009

    @Mārcis
    Nu kaut ko es sapratu bet nemaku pats izveidot jo nesmu vel tik pieredzejis tapec vai nevari iedot piemeru? tiesi kodu!

  9. druM
    18:12 on June 24th, 2009

    Sveicināti, bet man šis te iet tikai tad, ja es sekojošo rindu:

    $sql=”SELECT SQL_CALC_FOUND_ROWS * FROM `tabula` “.$_LIMIT;

    nomainu uz

    $sql=”SELECT SQL_CALC_FOUND_ROWS * FROM `tabula` LIMIT $_LIMIT”;

  10. Mārcis
    21:08 on June 24th, 2009

    druM, tā nevarētu būt, jo php sintakse pieļauj abus variantus, pirmais pat būtu ieteicamāks (tīri stila pēc).

  11. druM
    13:34 on June 25th, 2009

    Nu ja es lietoju pirmo variantu tad man nedarbojas mysql_fetch_object, uzmet kļūdu :/

  12. Mārcis
    15:26 on June 25th, 2009

    Ja kļūdu izmet tikai pie mysql_fetch_object(), tad tā nav php sintakses kļūda, bet mysql sintakses kļūda.
    Šādas problēmas nereti risina, apskatot kļūdas paziņojumu -

    mysql_query(...)or die(mysql_error());
  13. druM
    21:30 on June 25th, 2009

    Bet es nevaru uzzināt kļūdu, jo pierakstot klāt mysql_error() man neko neizmet, tas varētu būt tādēļ ka .$_LIMIT ir aiz Pēdiņām…

    Nu man tas kvērijs tad sanāk apmeram šāds:

    $sql=”SELECT SQL_CALC_FOUND_ROWS * FROM `tabula` “.$_LIMIT OR DIE(mysql_error());

    Viņam tādam arī ir jāizskatās ?

  14. Mārcis
    21:54 on June 25th, 2009

    Šī raksta komentāri nav īstā vieta, kur mācīties elementārus php pamatus (sintaksi)… Turklāt es tev devu piemēru.
    Bāžot visu ar karoti mutē, tu neko neiemācīsies.

    $sql = "SELECT SQL_CALC_FOUND_ROWS lauks1, lauks2 FROM `tabula`".$_LIMIT;
    $res = mysql_query($sql)or die(mysql_error());

    Un ieslēdz tak error_reportingu, citādi neredzi arī sevis ielaistās kļūdas php kodā.

    ini_set('display_errors', 1);
    error_reporting(E_ALL);
  15. druM
    23:19 on June 25th, 2009

    Labi, ceru uz turpmāko sadarbību caur e-mail ;)

  16. Mārcis
    13:03 on June 26th, 2009

    Cerība mirst pēdējā :)
    Es, diemžēl, neesmu labdarības organizācija.

  17. waplet
    14:57 on September 6th, 2009

    OMG Paldies tev mārci.. vis strādā perfekti.. liela buča tev :) )

  18. waplet
    19:57 on September 12th, 2009

    Hmm a kā uztaisīt lai izvadās visas lapas uzreiz nevis tikai nākamo rāda? nespēju saprast

  19. waplet
    20:08 on September 12th, 2009

    Atvainojos tomēr viss ir.. biju izdēsis mainot kodu

Leave a comment

RSS barotne komentāriem pie šī raksta