Yücel Alkan

Sonsuz Kategori Alt Kategori Zinciri

İç içe kategorileri ya da menüleri Hepsiburada, Vatan Bilgisayar veya bunlar gibi çok fazla ürün çeşidi olan sitelerde görmüşsünüdür. Örneğin; Bilgisayar > Dizüstü Bilgisayar > Oyun Bilgisayarı gibi. Çok karmaşık gibi görünen bu yapıyı aslında tek bir SQL tablosu ve birkaç satırdan oluşan PHP kodu ile oluşturmak mümkün. 

Bu yapıyı meydana getirmek için öncelikle SQL tablomuzu halledelim. SQL veritabanımızda kategoriler adında bir tablo oluşturuyoruz ve bu tabloya üç alan ekliyoruz;

  • id - int (auto_increment, key)
  • pid - int 
  • kategoriAdi - varchar(50)

Aşağıdaki linkten SQL dosyasını indirip çalıştırdığınız zaman hem kategoriler adında tabloyu oluşturmuş hem de içerisine verileri eklemiş olacaksınız.

SQL dosyasını indirmek için TIKLAYINIZ.

SQL dosyasını çalıştırdığınız zaman aşağıdaki tabloda kayıtların verilerin yer aldığı tablomuz oluşacaktır. 

id pid katagoriAdi
1 0 Bilgisayar
2 1 Dizüstü Bilgisayarlar
3 1 Masaüstü Bilgisayarlar
4 1 Oyun Bilgisayarları
5 2 Casper Notebook
6 2 Asus Notebook
7 4 Monster Notebook
8 4 MSI Notebook
9 0 Yazıcılar
10 9 Lazer Yazıcılar
11 9 Mürekkep Püskürtmeli Yazıcılar
12 9 Tanklı Yazıcılar
13 10 HP Yazıcılar
14 10 Canon Yazıcılar
15 13 HP M Serisi
16 13 Canon AirPrint Serisi

Bu tabloda yer alan pid değeri yani parent id değeri, o kategorinin bağlı bulunduğu üst kategorinin id değerini belirtiyor. Ana kategorilerin pid değeri ise 0 olarak belirlenmiş durumda. 

Gelelim, iç içe kategorilerin listelenmesine. Bu yapıyı oluşturmak için recursion olarak tanımladığımı bir fonksiyon türü kullanacağız. Recursion, kendi içerisinde tekrar çağrılan yani yinelenen fonksiyon yapısıdır. Daha fazla bilgi için bu linkteki bilgileri gözden geçirebilirsiniz.

İşte iç içe sınırsız kategori listeyen fonksiyonumuz;

function kategoriListe($id)
    {
        global $con;
        
        echo "<ul>";
        
        $kod="SELECT
              K.id, K.kategoriAdi,
              (SELECT COUNT(A.id) FROM kategoriler AS A WHERE A.pid=K.id ) as altKategoriSayisi
              FROM kategoriler AS K
              WHERE K.pid={$id}";
        $sql=mysqli_query($con,$kod);
        while($veri=mysqli_fetch_assoc($sql))
        {
            echo "<li>".$veri["kategoriAdi"];
            
            if($veri["altKategoriSayisi"]>0)
                kategoriListe($veri["id"]);
            
            echo "</li>";

        }
        
        echo "</ul>";
    }

Dikkat ettiyseniz kategoriListe fonksiyonumuz, şarta bağlı olarak kendi içinde tekrar çağrılıyor. İşte bu yapının adı recursion fonksiyon yapısıdır. Koddaki $con değeri ise mysqli fonksiyonundaki bağlantı değişkenini ifade ediyor. 

Aşağıdaki gibi fonksiyonumuzu çağırabiliriz;

kategoriListe(0);

İlk önce ana kategorileri listelemek için fonksiyonu çağırırken parametreye değer olarak 0 değerini gönderdik. 

Bu kodları çalıştırdığınız zaman aşağıdaki yapı gibi bir çıktınız olacaktır;

  • Bilgisayar
    • Dizüstü Bilgisayar
      • Casper Notebook
      • Asus Notebook
    • Masaüstü Bilgisayar
    • Oyun Bilgisayarları
      • Monster Notebook
      • MSI Notebook
  • Yazıcılar
    • Lazer Yazıcılar
      • HP Yazıcılar
        • HP M Serisi
      • Canon Yazıcılar
        • Canın Airprint Serisi
    • Mürekkep Püskürtmeli Yazıcılar
    • Tanklı Yazıcılar

Mysql veritabanımızda bulunan kategoriler tablomuza yeni kategori eklediğimiz zaman bu yapı otomatik olarak genişleyecektir. 

Yazıyla ilgili soru ve görüşlerinizi yorum olarak yazabilirsiniz. 

Hayırlı çalışmalar.

03.01.2019
94699
Yorumlar
Murat (29 Mayıs 2019 - 10:21)
Harika bir çözüm üretmişsin. İnternette bulabildiğim en kısa kodla sonuca ulaşılabilmiş bir script. Emeğine sağlık.
Yücel Alkan (05 Haziran 2019 - 20:24)
Faydalı olduysa ne mutlu. Hayırlı çalışmalar dilerim :)
Cevapla
mskirmizi (20 Ağustos 2019 - 13:57)
süper olmuş...
Yücel Alkan (31 Ağustos 2019 - 18:21)
Teşekkür ederim. Faydalı olmasına sevindim. :)
Cevapla
ibrahim (27 Eylül 2019 - 07:59)
Merhaba hocam soyagaci programi için bu tablo yapısını kullanmam yeterli olur mu ?
Yücel Alkan (30 Eylül 2019 - 18:55)
Merhabalar, listeleme işleminde Recursion kullanmanız sizi büyük bir dertten kurtarır. Ancak soy ağacının yapısını da bilmek gerekiyor. O zaman daha net konuşabilirim.
Cevapla
yasar (15 Aralık 2019 - 18:07)
hocam selam, güzel paylaşım yaptınız ama biraz eksik geliyor sanki gözüme. en azından fazla bilgisi olmayan biri için :) tam aradığım içerik bu bana bu konuda yardımcı olabilir misin? tşkler.
Yücel Alkan (08 Mart 2020 - 19:17)
Merhabalar. Olabildiğince basite indirmeye çalıştığım için olabilir. Bu işe yeni başlayanlar için biraz karmaşık bir konu.
Cevapla
Ahmet (10 Ocak 2020 - 02:19)
Merhabalar. Bir kategori silindiğinde tüm alt kategorilerin silinmesini istiyorum. Yani sizin örneğinizdeki Yazıcılar kategorisi silindiğinde tüm alt kategorileri silinmesi gerekiyor. Bu mümkün mü? Teşekkürler.
Yücel Alkan (08 Mart 2020 - 19:18)
Merhabalar. Tabi ki mümkün. Recursion kullanarak yapabilirsiniz.
Cevapla
Kıvanç (12 Mart 2020 - 11:57)
Tebrikler güzel ve kısa bir kod. Bir de select-option olarak yapsan süper olur. Alt kategorileri tireler yada boşluklar kullanılarak belirtilen.
Cevapla
mehmet (08 Mayıs 2020 - 23:11)
görünen oki her kategori için msql sorgusu yapılıyor buda msqli yoracaktır nacizane fikrim tek sorgu ile halletmektir
Yücel Alkan (09 Mayıs 2020 - 11:30)
Tek sorgu ile bu işin içinden çıkmak zor olabilir. Ancak ben yazımda en ideal ve en iyi yöntemin bu olduğunu belirtmedim zaten. Sonsuz kategori zinciri için basit ve kolay bir yöntem diyebiliriz.

Daha iyi çözüm yolları var mıdır? Tabi ki vardır. Mesela aklıma gelenleri yazmak istiyorum.

1. Kategori zinciri çok sık değişen bir sayfa değil. Bu nedenle her seferinde kategori zincirinin SQL sorgusu ile yeniden oluşturulmasındansa menu.html adında statik bir sayfa oluşturulur. Kategori zincirinde meydana gelen her değişiklik sonrası (güncelleme, silme, ekleme) menu.html sayfası basit bir tetikleme sonrasında yeniden oluşturulur. Bu sayede belki de ayda bir iki kez SQL sorgusu çalıştırılmış olur.

2. yöntem olarak bu iş front-end tarafında yapılabilir. API isteği ile tüm kategoriler bir dizi içine alınıp, kategori > alt kategori front-end tarafında oluşturulabilir. Bu sayede tek SQL sorgusu ile bu iş bitmiş olur. Vue.js ön tarafta bu iş için ideal olabilir.

Akıl akıldan üstündür. Daha iyi fikri olan dostlar bu yorum altında yazarlarsa içeriği gören arkadaşlar için de güzel bir kaynak olmuş olur. :)
Cevapla
Sadık (24 Haziran 2020 - 17:56)
Merhaba peki kategorileri form aracılığıyla nasıl veritabanına kaydederiz. Numaralandırma işlemi nasıl yapılır.
Cevapla
raimberdi (10 Kasım 2020 - 11:51)
merhaba hocam mantık olarak cok güzel bir yöntem uygulamışsınız güzel ama bunu yazdırırken nasıl yapa bilirim hocam newData[i] = { title: data[i].aciklama, url: '', submenu: { type: 'menu', menu: [ { title: 'deneme', url: '/' }, ],
Cevapla
codeboss (21 Aralık 2020 - 13:18)
verdiğiniz örnek kod ve sql yapısına göre bu fonksiyon çalışmaz, kod uyumsuz.
Yücel Alkan (29 Aralık 2020 - 10:23)
Merhabalar, test etmediğim kodları siteme yüklemiyorum. Yani çalışıyor hatta yukarıda çalıştığı zaman sayfaya nasıl bir çıktığı geldiğine dair görsel de koydum. Siz bu kodları indirip, test edip, çalıştırdınız mı?
Cevapla
Oguzhan (08 Mart 2021 - 00:49)
"SELECT K.id, K.kategoriAdi, (SELECT COUNT(A.id) FROM kategoriler AS A WHERE A.pid=K.id ) as altKategoriSayisi FROM kategoriler AS K WHERE K.pid={$id}" Hocam aslında şu karmaşık sorguyu açıklasanız sonsuz kategoriden daha çok makbule geçecektir. bazı bilgilere erişmek zor. sanırım sorgu içinde sorgu yapmışsınız. AS veriyi yeni değerlere atamak için kullanıldı sanırım. k.id mesele oradaki k. ne amaçla kullanıldı. işlem sırasına göre açıklarsanız güzel olur.
Shumaf (10 Ocak 2022 - 14:10)
Oradaki K. kategoriler tablosunun kısaltılmış hali. Dikkat ederseniz sonunda da kategoriler AS K şeklimde tanımlamış.
Cevapla
Aytaç GÜL (05 Mart 2022 - 16:46)
Çok pratik bir yol ama ama kategori listesine link eklemek istediğimde linkleri oluşturmakta zorlaniyorum. örn. "urunler/windows/office21/" gibi bir link yaratmak istediğimde üst kategorinin bilgisini nasıl verebilirim ?
Cevapla
Farid (24 Ocak 2023 - 04:06)
Çok teşekkürlek kod için. Peki Casper markasının hem dizistü hem de masaüstü ürünleri varsa. Bu yapıda onu nasıl yapıcaz? masaustu_casper ve dizustu_casper diye yeni örnekmi oluşturmalıyız?
Cevapla
Yorum Yapın