RSS

PHP ile sayfalama

63 28 Temmuz 2012 ~ Musa Avcı — Orta

İçerikleriniz çoğaldı, bayağı kaynağınız ve birikiminiz oldu. Ve artık bunları sayfalamanın zamanı geldi. MySQL veritabanı tablosu verileri ile sayfalama yapımı anlatacağım bu yazıda genel sayfalama mantığını anladıktan sonra başka kaynaklardan gelen (array, xml, vs.) verilerle de sayfalama yapabileceğinize inanıyorum.

Toplam sayfa sayısını bulmak

Sayfalama olayına öncelikle toplam sayfa sayısını bulmakla başlayalım. Bu işlem için toplam içerik sayısını bir sayfada göstereceğimiz içerik sayısına böleceğiz, çıkan sonucu ise ceil fonksiyonu ile yukarı yuvarlayacağız.

$sayfada = 5; // sayfada gösterilecek içerik miktarını belirtiyoruz.

$sorgu = mysql_query('SELECT COUNT(*) AS toplam FROM mesajlar');
$sonuc = mysql_fetch_assoc($sorgu);
$toplam_icerik = $sonuc['toplam'];

$toplam_sayfa = ceil($toplam_icerik / $sayfada);

Buradaki ince noktalardan birisi yukarı yuvarlamak. Diyelim her sayfada 5 içerik istiyoruz ve 12 içerik var, bu durumda (12 / 5 = 2.4), ceil fonksiyonu ile bu rakamı 3’e yuvarlıyoruz. Eğer normal round fonksiyonunu kullanırsak böyle bir durumda 2 sayfamız olur ve son 2 içerik görünmez.

Eğer çok fazla içeriğiniz varsa, her sayfada toplam içerik sayınızı sayan bu SQL sorgusunu çalıştırmak yerine bir şekilde cache uygulayıp oradan okutmanız performans açısından daha faydalı olacaktır.

Sayfanın içeriğini listelemek

Bir sayfada ne kadar içerik olacağını belirledik, şimdi gelelim bulunduğumuz sayfaya göre içeriklerimizi listelemeye. Bu noktada artık kullanıcı tarafından sayfa sayısını almanın zamanı geldi. Ben örneğimde “sayfa” GET verisi ile alacağım, yani index.php?sayfa=2 şeklinde olacak. İsterseniz “s”de idealdir.

// eğer sayfa girilmemişse 1 varsayalım.
$sayfa = isset($_GET['sayfa']) ? (int) $_GET['sayfa'] : 1;

// eğer 1'den küçük bir sayfa sayısı girildiyse 1 yapalım.
if($sayfa < 1) $sayfa = 1; 

// toplam sayfa sayımızdan fazla yazılırsa en son sayfayı varsayalım.
if($sayfa > $toplam_sayfa) $sayfa = $toplam_sayfa; 

Eklediğimiz bu ufak koşullar ile geçersiz yazılan sayfa numaralarından doğacak olan hataları da engellemiş oluyoruz. Ayrıca değişkeni tanımlarken başına (int) eklememiz sayı haricinde yapılan girişleri geçersiz kılıyor. Bu ifadeyi NO, ID gibi dışardan gelen verileri çekerken de kullanabilirsiniz.

Hangi sayfada olduğumuzu da belirlediğimize göre artık içeriklerimizin istenilen kısmını listeleyebiliriz.

// kaçıncı içerikten başlanacağını ifade edecek limit değeri.
$limit = ($sayfa - 1) * $sayfada;

$sorgu = mysql_query('SELECT * FROM mesajlar LIMIT ' . $limit . ', ' . $sayfada);

while($icerik = mysql_fetch_assoc($sorgu)) {
   // ...
}

Sanırım kilit ve kafa karıştıran noktası burası. LIMIT ifadesi ile tüm içerikler arasından bizim istediğimiz adet ve aralıktaki içerikleri istiyoruz. Normalde sadece “LIMIT 10” dediğimizde 10 adet içerik verir. Fakat virgül ile ikinci bir sayı daha girdiğimizde kaçıncı sıradan sonra vereceğini ifade eder.

Yani “LIMIT 0, 5” dediğimizde 0. içerikten yani ilk içerikten sonra 5 tane ver diyoruz, bu bizim ilk sayfamız oluyor. 2. sayfa için “LIMIT 5, 5” yani 5. içerikten sonra 5 tane göster diyoruz. 3. sayfa için “LIMIT 10, 5”. Bu ifade için “($sayfa – 1) * $sayfada” işlemimizi yapıyoruz.

Sayfa sayılarını gösterme

Son olarak en alta sayfa sayılarını göstereceğiz. Bunun için döngü ile toplam sayfa sayısı kadar link oluşturacağız. Ayrıca bulunduğumuz sayfayı da dikkate alarak o sayfayı yazarken link yapmayacağız.

for($s = 1; $s <= $toplam_sayfa; $s++) {
   if($sayfa == $s) { // eğer bulunduğumuz sayfa ise link yapma.
      echo $s . ' '; 
   } else {
      echo '<a href="?sayfa=' . $s . '">' . $s . '</a> ';
   }
}

Sonuç

Şimdi tüm hepsine bir arada bakalım ve daha rahat anlayalım.

$sayfada = 5; // sayfada gösterilecek içerik miktarını belirtiyoruz.

$sorgu = mysql_query('SELECT COUNT(*) AS toplam FROM mesajlar');
$sonuc = mysql_fetch_assoc($sorgu);
$toplam_icerik = $sonuc['toplam'];

$toplam_sayfa = ceil($toplam_icerik / $sayfada);

$sayfa = isset($_GET['sayfa']) ? (int) $_GET['sayfa'] : 1;

if($sayfa < 1) $sayfa = 1; 
if($sayfa > $toplam_sayfa) $sayfa = $toplam_sayfa; 

$limit = ($sayfa - 1) * $sayfada;
$sorgu = mysql_query('SELECT * FROM mesajlar LIMIT ' . $limit . ', ' . $sayfada);

while($icerik = mysql_fetch_assoc($sorgu)) {
   // ...
}

for($s = 1; $s <= $toplam_sayfa; $s++) {
   if($sayfa == $s) { // eğer bulunduğumuz sayfa ise link yapma.
      echo $s . ' '; 
   } else {
      echo '<a href="?sayfa=' . $s . '">' . $s . '</a> ';
   }
}

Çok daha fazlası

Yukarıda anlattığım bu yöntem ile artık içeriklerinizi sayfalı yapabilirsiniz. Ama biraz ileri görüşlü olursak ya da elimizde çook fazla içerik ve bu nedenle yüzlerce sayfamız varsa; 1’den 200’lere kadar çok uzun sayfalar bağlantımız olur. Hem çirkin hem de kullanıcı dostu olmayan bir görüntü ile karşılaşırız. Bunu önlemek için ne kadar çok sayfamız olursa olsun kullanıcını o an kaçıncı sayfada ise ona ilaveten sonraki ve önceki 5-10 sayfayı göstermeliyiz. Yani şu şekilde;

<<İlk sayfa <Önceki 35 36 37 38 [39] 40 41 42 43 Sonraki> Son sayfa>>

Ben bu olay için bir kod bloğu hazırladım, bunu direkt çalışmanıza dahil edip kullanabilir ya da inceleyip daha farklı versiyonlarını yazabilirsiniz. Dikkat edilmesi gereken nokta; bu yöntemin doğru ve güzel çalışması için $sayfa_goster değerine her zaman tek sayı girin. Bu sayede kullanıcı bulunduğu sayfayı yukarıdaki örnekteki gibi ortada görür.

// yukarıdan geldiği varsayılan değişkenler:
// $toplam_sayfa ve $sayfa

$sayfa_goster = 11; // gösterilecek sayfa sayısı

$en_az_orta = ceil($sayfa_goster/2);
$en_fazla_orta = ($toplam_sayfa+1) - $en_az_orta;

$sayfa_orta = $sayfa;
if($sayfa_orta < $en_az_orta) $sayfa_orta = $en_az_orta;
if($sayfa_orta > $en_fazla_orta) $sayfa_orta = $en_fazla_orta;

$sol_sayfalar = round($sayfa_orta - (($sayfa_goster-1) / 2));
$sag_sayfalar = round((($sayfa_goster-1) / 2) + $sayfa_orta); 

if($sol_sayfalar < 1) $sol_sayfalar = 1;
if($sag_sayfalar > $toplam_sayfa) $sag_sayfalar = $toplam_sayfa;

if($sayfa != 1) echo ' <a href="?sayfa=1">&lt;&lt;İlk sayfa</a> ';
if($sayfa != 1) echo ' <a href="?sayfa='.($sayfa-1).'">&lt;Önceki</a> ';

for($s = $sol_sayfalar; $s <= $sag_sayfalar; $s++) {
	if($sayfa == $s) {
		echo '[' . $s . '] ';
	} else {
		echo '<a href="?sayfa='.$s.'">'.$s.'</a> ';
	}
}

if($sayfa != $toplam_sayfa) echo ' <a href="?sayfa='.($sayfa+1).'">Sonraki&gt;</a> ';
if($sayfa != $toplam_sayfa) echo ' <a href="?sayfa='.$toplam_sayfa.'">Son sayfa&gt;&gt;</a>';

1000+ sayfadan çok daha ötesi için burada anlattığımız “LIMIT 10, 5” ifadesini kullanmak yerine şu slaytta anlatılan yöntemleri inceleyebilirsiniz. Eğer fırsat olursa buradaki slaytta bahsi geçen yöntemleri de ayrı bir yazı ya da bu yazıya ek olarak yazmayı düşünüyorum.

Bu konuyla alakalı aklınıza takılan soruları ya da uyguladığınızda karşılaştığınız sorunları paylaşmaktan çekinmeyin.

Bir sonraki PHP serüveninde görüşmek üzere, hayırlı ramazanlar!

Etiketler:

Yazılanlar ilgini çektiyse, yenilerinden haberdar olmak için e-mail bültenine abone olabilirsin.

"PHP ile sayfalama" yazısı için 63 yorum yapılmış.

  1. tamer dedi ki:

    Musa eline sağlık çok güzel bir makale olmuş. Yorum olarakda https://github.com/jney/jquery.pageless bunu not düşeyim gelenlere yardımcı olmuş oluruz.

  2. Hakan Bulgurlu dedi ki:

    Bu Sayfalama Kodu Gerçekten Çok işime Yaradı Şu an Bütün Sitelerimde Bu Kodu Kullanıyorum Sayfalamayı Siteme Uyarlamak neredeyse tam 3 dakikamı Almıştır Herşey Çok Net Bir Şekilde Anlatılmış Elinize Sağlık Diyorum Çok Sağolun.

  3. emre dedi ki:

    ellerinize sağlık gerçekten çok işime yarayacak

  4. ilhami dedi ki:

    musacığım eline emeğine sağlık kardeşim

  5. Phpci dedi ki:

    Elinize sağlık süper bir makale o slayttakileri de bu yazıya dahil ederseniz sevinirim. İyi çalışmalar…

  6. Hüseyin dedi ki:

    hocam çok sağolasın onca sitenin onca örneğin içinde tek seferde ve başarışı çalışan paylaşımın şçşn çok saol.

  7. engin dedi ki:

    Konuyla alakasız bişey soracam kodları renklendirmek için hangi plugin kullanıyorsunuz.

  8. mehmet kemal dedi ki:

    Aradığım bir içerik ancak, bunu yorum kısmına da uygulayabilir miyiz acaba ?

  9. Erhan Şentürk dedi ki:

    Hocam Merhaba. elimde bulunan sayfalama kodlamasıyla sizinde kodlarınızdan faydalanarak güzel bir işlem gerçekleştirdim. fakat aklıma takılan bir konu var. sayfama yaparken verileri alt alta sıralıyoruz bu verileri yan yana 3 tane alt alta 5 satır olcak şekilde nasıl yapabiliriz.

  10. Erhan Şentürk dedi ki:

    Hocam Eline sağlık çok güzel olmuş fakat bende bulunan sayfalama koduna uygularken alt alta basıyor içerikleri. size elimde bulunan kodu nasıl gösterebilirim. bi baksanız.

  11. Erhan Şentürk dedi ki:

    hallettim hocam tşkler.

  12. Erhan Şentürk dedi ki:

    Musa Hocam. Sayfalama konusunda bir başka kodlamada yine karşıma bir sorun çıktı. mysql da arama yaptırıyorum yani arama motoru yaptım ufak bişe. aranan kelimeler tabloda kayıtlıysa listeliyor fakat bunları sayfalamak istiyorum. nasıl yapabilirim.

  13. Talip Durmuş dedi ki:

    Teşekkürler sırf bunun için class indirmiştim gerek yokmuş güzel yöntem bulmuşsun Emeğine Sağlık..

  14. gorkem dedi ki:

    tsk ederim.Sayfalama örneğinizi inceleyeceğim

  15. UnaL dedi ki:

    Hocam güzel yazı olmuş. Ancak çözemediğim bir sorunum var. Sayfalar listelendikten sonra sayfa sayısı linkine tıkladığımda sayfa açılmıyor. Sebebi ne olabilir ?

    • Musa Avcı dedi ki:

      hazırladığınız link yapısı hatalı olabilir, sorun hakkında daha iyi yardımcı olabilmemiz için ilgili kısmın kodunu paylaşabilirsiniz.

  16. Phpci dedi ki:

    Bunu bir fonksiyon haline getirmek istersek nasıl yapabiliriz? Her seferinde kod kalabalığından kurtulmuş oluruz böylece.

  17. Hüseyin dedi ki:

    Hocam eline sağlık çok güzel makale olmuş. Ben php’de yeniyim o yüzden takıldığım bir yer var. Kodları yerleştirdim. En alta da 1 2 3 diye sıralandı. Hepsi çok iyi ama sayfa açılınca 15 gösteri yapıyor. 2 yi tıklayınca yine aynı sayfa 15 içerik 3 ü tıklayınca da yine aynı sayfa. Yerleştirmede bir yanlışım mı oldu?

  18. mustafa dedi ki:

    hocam ellerinize sağlık güzel bir kaynak olmuş….

  19. Volkan YILDIZ dedi ki:

    Musa çok sagol sitende bir çok konudan faydalandım. Hakkını helal et.

    Aradığım konulardan biride buydu. Ama benim veritabanındaki bilgileri sondan başa çekmem gerekiyordu. Onu da;


    $sorgu = mysql_query(‘SELECT * FROM mesajlar Order By id DESC LIMIT ‘ . $limit . ‘, ‘ . $sayfada);

    şeklinde “Order By id DESC” ekleyerek hallettim. Umarım benim aradığımı arayan arkadaşlara faydalı olur 🙂

  20. bulut dedi ki:

    çok teşekkür ederim.elimdeki projemde çalışmanızı kullanıyorum.ilk denemede başarısız oldum ama ikinci denememde sonuç çok iyi oldu 🙂

  21. ali dedi ki:

    Öncelikle çok açık bir anlatımınızın olduğunu söylemek istiyorum.
    İki sorum var:
    1- Her seferinde mysql dan veri çekerek sayfa sayısını hesaplatmak yerine içerik ekledikçe güncellenen bir txt dosyasına sayfa sayısını yazdırıp ondan çektirsek daha performaslı olur mu?
    2- ilk başta niye mysql_num_rows kullanmak yerine diziye aktarıp toplam konu sayısını hesaplattık?
    Yardımlarınız için teşekkürler.

  22. serkan akpınar dedi ki:

    ellerine saglık kardeşim oyle cok yorum yapmam ama bu guzel sistem yorum yapayım dedim gayet başarılı bir sistem tesekkurler

  23. Fatih dedi ki:

    Merhabalar anlatımınız çok hoş ve sadece yalnız takıldıgım bir nokta var sayfa linkleri verirken listelenen kategoriye göre listelemesini istiyorum örnek vermek gerekirse id=345 olan kategoriye baglı ürünleri listeletiyorum ama sayfa değiştirilince urunler gelmiyor link şu şekilde
    ‘.$s.’
    Yardımlarınız için çok teşekkürler

  24. Minecraft dedi ki:

    Çok faydalı bir yazı olmuş, teşekkürler.

  25. Umut dedi ki:

    benim sorum biraz daha değişik olacak.. Sayfalamayı yapıyorum hiçbir sıkıntım yok. Ancak ben bunu yorum scriptimde kullanıyorum. Kullanıcı yorum yaptığı zaman doğal olarak bir onay sürecim var. Onaylamadığım yorumlar gözükmüyor doğal olarak ancak yorum yaptıkça sayfalar çoğalıyor. Ne yaptıysam önüne geçemedim bu sorunu nasıl halledebilirim. Yani yorum onaylanmadıysa sayfalama yapmaması için ne yapmam lazım kurduğum if ler bir işe yaramadı

  26. Fatih dedi ki:

    Teşekkürler.Çok iyi bir anlatım olmuş.

  27. Ahmet dedi ki:

    Musa eline sağlık gayet net temiz anlatmışsın.. bahsettiğin slayttaki yöntemle ilgili makaleyi hazırladınmı ? merak ettim açıkcası limit m,n kullanmayın demiş şaşırdım açıkcası…

  28. olcay dedi ki:

    gerçekten süper bir anlatım. videoya çekilse bu kadar güzel olamazdı herhalde. başarılar

  29. Rıza dedi ki:

    Hocam uzun zmandır bu sayfalama yapısını kullanıyorum. Şimdiye kara bi sıkıntım yoktu lakin şimdi var. sayfa yapım index.php?id=$u_id şeklinde olunca sayfalama yaparken yapılmış gibi gösteriyor. linkin soonuna sayfa=1 sayfa=2 diye gidiyor. Ohh oldu dedim. Sonra bi baktım kategorideki herşeyi çekiyo. Referanslar tablosunda her firmanın resmi ayrı ekleniyor. sayfalama yaparken bütün herşeyi çekiyor. referansın id’sine göre çekmek istedim beceremedim. bi örnek sunar mısınız. çok dua ederim yeminle

  30. selçuk dedi ki:

    üstadım gerçekten çok güzel bir konu hazırlamışsın emeğine sağlık, normalde kolay kolay yorum yazmam hiç bir yere ama hakikaten burada bi emek sarf edilmiş, kodlarını kullanıyorum birazda kendime uyarlayıp geliştirdim. hakkını helal et inş.

  31. Aykut dedi ki:

    Bende “SyntaxHighlighter” kullanıyorum, fakat tema ayarı nasıl oluyor böyle bir makele yazarmısınız?

  32. Ömer dedi ki:

    Merhaba Hocam. Öncelikle elinize sağlık çok güzel ve sade anlaşılır bir yazı olmuş. Benim söyle bir sorum olacaktı mesela tahmin tablom var ve bu tabloda “ad soyad durum” kolonları var ve bu durum kolonu 0-1-2 degeri alıyor. eger 0 ise listeye eklenecek. 1 veya 2 ise eklenmeyecek. Bunu nasıl halledebilirim acaba?Şimdiden teşekkürler.

  33. Ahmet dedi ki:

    sayfalamayi sizinle ögrendim, tesekkurler.

  34. Erdem OFLAZ dedi ki:

    Eline emeğine sağlık ustam . Benim bir sorum olacak. benim arkadaş bunu 5 satırla bitirmiş baktım mantıklı da yapmış. Bunun daha kısa bir yolu var mıdır ?Teşekkürler

  35. Ahmet dedi ki:

    Üstat teşekkürler baya işime yaradı

  36. Fatih Öztürk dedi ki:

    Hocam cogu seyi burdan ogrendim bilgi birikiminiz saglam turkce aramalarda hep basta cıkıyodunuz tessekkur ediyim istedim kendi web sitemi yazarken kaynaklarınızı paylasacagım izniniz olursa (altta icerigi kopyalaya bilirsiniz yazmısınız ) ben yinede soyliyeyim istedim her sayfanız icin turkyazılımı icin size cok tessekkurler…

  37. Onur KAYA dedi ki:

    Merhaba,

    Emekleriniz ve paylaşımınız için teşekkür ederim. Sayfalama çalışıyor. Fakat şöyle bir sorun ile karşılaştım.

    Sayfalama yaparken bazı kayıtları es geçip göstermiyor, diğer sayfaya geçtiğimde önceki sayfada gösterdiği kayıtlardan tekrar gösterim yapıyor. ancak ilk sayfada es geçtiği kayıtları bu sayfada da göstermiyor.

    Sayfada gösterilecek kayıt sayısını 25 yapınca es geçtiği kaydı gösteriyor, sorunsuz çalışıyor.

    Kodlar aşağıdaki adreste. nerede hata yapıyorum? yardımcı olabilir misiniz?
    http://pastebin.mozilla.org/7727226

    Sayfalama sınıfı da aşağıdaki adreste:
    http://pastebin.mozilla.org/7727272

    Ekran görüntüleri:
    http://imageshack.com/a/img673/555/UcTYQq.png
    http://imageshack.com/a/img538/339/D4YVqS.png
    http://imageshack.com/a/img661/5971/1AurdZ.png

    Tekrar teşekkürler.

    • Onur KAYA dedi ki:

      Sorunu çözdüm. Aslında ortada sayfalama ile ilgili bir sorun yokmuş. sıralama filitremden kaynaklı bir sıkıntıymış. Düzelttim.

  38. Sefa Can dedi ki:

    Merhaba
    Bu konuyu normal sayfalama olarak yapabildim teşekkürler ama,
    php arama yaparak istediğim veriyi çekebiliyorum, sayfalama yapamadım nasıl olucak?

  39. Nazif ÖZTÜRK dedi ki:

    arkadaşlar yapamadım yardımcı olurmusunuz. kodlar aşağıdadır.

    http://pastebin.com/hK2x2p4c

  40. PHP ile ilgili ne ararsam sonunda kendimi phpr da buluyorum. Aynı şekilde en net bilgiye de burada ulaşıyorum. Teşekkürler, Musa AVCI.

  41. Savaş ŞİMŞEK dedi ki:

    Kardeşim Emeğine Ellerine sağlık..5 dakkada yaptım valla..saolasın

  42. barış dedi ki:

    Öncelikle teşekkürler hocam. Bu sistemi arama sonucunda listelenen verilerde nasıl kullanabiliriz?

  43. Samet dedi ki:

    Hocam teşekkürler. gercekten cok güzel bir anlatım ve tam istenilen özellikte.

  44. mehmet dedi ki:

    merhaba. deniyorum fakat bende sadece sayfa numaraları çıkıyor. Üzerine tıkladığımda sayfaya gidiyor ama içeriği göstermiyor. ne içerik ne de içerik başlığı listelenmiyor.

  45. elliot dedi ki:

    Senden hızlısı ibm computerda

  46. elliot dedi ki:

    O kadar yabancı sayfalarda aradık felan buraya bi geliyorsun o kadar ara o kadar gold almış stackoverflow adamlarından 2 kat iyi hizmet bi anda çözüm thanks dude thanks

  47. elliot dedi ki:

    Ayrıca açık kaynağın dibi ya “Bu blogdaki tüm içerikleri kopyalayabilir, değiştirebilir, silebilir, kaynak göstermeden paylaşabilirsin” seviyorum bu siteyi

  48. Burak dedi ki:

    Hocam gerekli açıklamaları ve istediğim özelliği tam olarak resimde anlattım.

    http://i.hizliresim.com/jjm9Bg.png

    Cevabınızı bekliyorum, kolay gelsin.

  49. Mustafa dedi ki:

    mysql_query geçersiz.
    mysql_fetch_array gibi şeyler geçersiz. Pdo hali ile değiştirilecekler mi?

  50. barış dedi ki:

    güzel anlatım

  51. Uğur dedi ki:

    Ellerine Ağzına Sağlık Harika Bir Anlatım.

  52. Uğur Erbil dedi ki:

    Hocam PDO ya Nasıl Çevireceğiz Bunu ?

  53. Umut dedi ki:

    Teşekkürler

  54. Murat SARI dedi ki:

    Teşekkürler çok faydalı oldu

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir