Hemen hemen her sitede etiket bulutu ile karşılaşıyorsunuzdur. Ben de bu yazımda basit bir etiket bulutu yapımını anlatmaya çalışacağım.
Etiketler sitemizde yayınladığımız yazılarda yazılarımızı ifade ederler ve genelde bir kelimeden oluşurlar. Örneğin ben bu yazı için "etiket", "etiket bulutu", "tag", "tag cloud" şeklinde etiketler ekledim.
Etiket bulutu oluşturmak için elimizde etiketler ve bu etiketlerin kaç defa kullanıldığı bilgileri olmalıdır. Etiketlerin kaç defa kullandığı bilgisini etiketlerimizin yazı font büyüklüğünün belirlenmesinde kullanacağız. Peki bu verileri tutan veri tabanı tablolarımız nasıl olmalı ?
Etiket bulutu oluşturmak için 3 adet tablomuz bulunmaktadır. Bu tablolar "etiketler", "yazilar", "yazi_etiket_iliskileri" şeklindedir. Yazılarımızı "yazilar" tablosunda, etiketlerimizi "etiketler" tablosunda, etiketlerin hangi yazıya ait olduğunu ise "yazi_etiket_iliskileri" tablosunda tutacağız. Tablolarımız son görünümü aşağıdaki gibi olacak.
"yazilar" Tablosu
- yazi_id
- baslik
- yazi
"etiketler" Tablosu
- etiket_id
- etiket
- yazi_adedi
"yazi_etiket_iliskileri" Tablosu
- yazi_id
- etiket_id
Tablolarımız bu şekilde olacak. Sql kodlarını veriyorum.
CREATE TABLE `yazilar` ( `yazi_id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT , `baslik` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , `yazi` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , PRIMARY KEY (`yazi_id`) ); CREATE TABLE `etiketler` ( `etiket_id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT , `etiket` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , `yazi_adedi` int(11) UNSIGNED NOT NULL , PRIMARY KEY (`etiket_id`) ); CREATE TABLE `yazi_etiket_iliskileri` ( `etiket_id` int(11) UNSIGNED NOT NULL , `yazi_id` int(11) UNSIGNED NOT NULL ) ;
Sql kodumuzu yazmadan önce "etiketler" tablosundaki yazi_adedi adlı sütunu neden kullandığımız açıklamak istiyorum. Ben yazıyı eklerken kullandığım etiketin yazı adedini güncelleyerek etiketler tablosunda tutmayı tercih ediyorum böylece sql sorgumuz sistemi fazla yormadan hızlı bir şekilde gerçekleşecektir. Aksi taktirde etiketlerinin kullanım adedini almak için sorguda join kullanmamız gerekecekki bu da sorguyu yavaşlatacaktır. Fakat siz dersenizki ben yazı eklerken etiket adedeni güncellemekle uğraşamam yazi_adedi sütununu kaldırabilirsiniz. İsterseniz "yazi_adedi" sütunu kullandığımızda ve kullanmadığımızdaki sorgularımızı yazalım.
"yazi_adedi" sütunu olduğunda sql sorgusu
SELECT etiket_id,etiket, yazi_adedi FROM etiketler ORDER BY yazi_adedi DESC LIMIT 10
"yazi_adedi" sütunu olmadığında sql sorgusu
SELECT e.etiket_id,e.etiket, COUNT(*) AS yazi_adedi FROM etiketler AS e INNER JOIN yazi_etiket_iliskileri AS yei ON k.etiket_id=yei.etiket_id GROUP BY yei.etiket_id ORDER BY yazi_adedi DESC LIMIT 10
"yazi_adedi" sütunu kullanıp kullanmamak artık size kalmış olaydır.
Ben yine de "yazi_adedi" sütununu kullanacak olan arkadaşlarımız için yeni yazı elediğimizde veya güncellediğimizde o yazıya eklediğimiz etiketlerin yazi_adedi'ni güncelleyen sorguyu veriyorum.
UPDATE etiketler as e SET yazi_adedi=( SELECT COUNT(*) FROM yazi_etiket_iliskileri as yei INNER JOIN yazilar as y ON yei.yazi_id=y.id WHERE yei.etiket_id=e.etiket_id ) WHERE e.etiket_id IN ('16', '21')
Yazı adedini güncelleyen sorgmuzda where koşulunda vermiş olduğum '16' ve '21' değerleri yazıya eklemiş olduğumuz etiketlerin etiket id'dir yani sizin sorgunuzda değişecek olan kısım.
Etiket bulutu oluşturan php fonksiyonumuz.
<?php function etiket_bulutu($etiketler = array(), $ile_birlestir=' '){ $max_adet = 0 ; //en çok kullanılan etiketin yazı adedini alıyoruz foreach($etiketler as $index => $etiket) { if ($etiket['yazi_adedi'] > $max_adet) $max_adet = $etiket['yazi_adedi']; } unset ($etiket); $etiket_bulutu = array(); //Bütün etiketlerin font büyüklüğünü belirleyen for döngüsü foreach($etiketler as $etiket) { //etiketin yazı adedini maksimum yazı adedine bölerek yüzdesini buluyoruz $yuzde = ($etiket['yazi_adedi']/$max_adet)*100; // Yüzde aralıklarına göre font büyüklüğü belirleniyor if($yuzde >= 98) $size = 2.0; else if($yuzde >= 80) $size = 1.7; else if($yuzde >= 70) $size = 1.6; else if($yuzde >= 60) $size = 1.5; else if($yuzde >= 50) $size = 1.3; else if($yuzde >= 40) $size = 1.1; else if($yuzde >= 30) $size = 1.0; else if($yuzde >= 20) $size = 0.8; else if($yuzde >= 10) $size = 0.7; else if($yuzde >= 5) $size = 0.7; else $size = 0.7; $etiket_bulutu[$etiket['etiket']] = '<a href="#etiket_linki" style="font-size: '.$size.'em" title="'.$etiket['yazi_adedi'].' adet yazı bulunmaktadır" >'.$etiket['etiket'].'</a> '; } ksort($etiket_bulutu); //diziyi key değerlerine göre sırala return implode($ile_birlestir, $etiket_bulutu); }
Bu fonksiyonumuz iki adet parametre alıyor. Birincisi etiket bulutu oluştururken kullanılacak olan etiketler, diğer parametremiz ise etiketlerin arasına koyulacak olan karakter.
Örnek Kullanım
$etiketler = array( array('etiket'=> 'etiket 1','yazi_adedi'=>5), array('etiket'=> 'etiket 2','yazi_adedi'=>3), array('etiket'=> 'etiket 3','yazi_adedi'=>1), array('etiket'=> 'etiket 4','yazi_adedi'=>6), array('etiket'=> 'etiket 5','yazi_adedi'=>10), array('etiket'=> 'etiket 6','yazi_adedi'=>3) ); echo etiket_bulutu($etiketler, ' ');
Ben fonksiyonun örnek kullanımında etiketler dizisini elle oluşturdum ama siz o etiketleri veritabanından çekip benim verdiğim örnekte kullandığım dizi haline getirip fonksiyona parametre olarak göndermelisiniz.
Bu sistemi serkandaglioglu.com'da da kullanmaktayım. Sidebardaki etiket bulutunu burdaki yöntemle oluşturdum.
Elimden geldiğince mantığını anlatmaya çalıştım. Faydalı olması dileğiyle.
Bende kelime bulutu tadında bir yorum bıraksam… :)
’ Php ve mysql ile etiket bulutu oluşturmak ’ yazınızı çok beğendim. Bu arada yazınızda , mysql veritabanı ilişkileri konusunda da bilgiler var. ’ mysql veri tabanında, tabloları nasıl ilişkilendirebilirim ?’ sorusuna yanıt almak isteyen arkadaşlar için güzel bir giriş , elinize sağlık…
bende güzel yorumun için teşekkür ederim Batuhan ...
Bilgiler güzel ama siteme entegre edemedim bir türlü . resim paylaşımı yapılan bir site yapıyorum. kullanıcının resmi yüklerken resme etiket de girmesini istiyorum ve etiketleri de veri tabanında saklamak istiyorum. ama beceremedim bir türlü :-(
nerede takıldığını söylersen yardımcı olabilirim. Yukarıda anlattıklarımı takip ettiğin zaman sorun yaşamayacağını düşünüyorum
mysql’den yazılar tablosuna ‘yazi_etiketleri’ isimli bir alan oluşturup, etiketleri bunun içerisine girsek nasıl çekebiliriz? yani yazıyı yazarken etiketler bölümüne “google chrome, google, indir” yazdım diyelim. ben bunu etiket.php=etiket=google sayfasında nasıl listeyebilirim?
Bu sorgu işini görür galiba.
Sizce bu sistemi fazlası ile yormaz mı? JSon olarak tüm etiketleri tek tabloda tutsanız daha mantıklı değil mi?Her etiket için mysql de yeni bir satır oluşturulması mantıklı gelmiyor.Binlerce etiket olduğu zaman ki bu da binlerce satır demek sorunlar çıkacağını düşünüyorum (overload vs…)
zaten etiketler tek tabloda tutuluyor(“etiketler” tablosu). Siz tek sütunda tutmayı kasdediyorsunuz galiba? Kafanızdaki tablo yapısını buraya tam olarak yazarsanız hangisinin daha performanslı olduğunu deneyebiliriz. Böylece faydalı bir araştırma yapmış oluruz.
Evet tek sutunda tutmayı kastetmiştim.Peki ozaman şöyle açıklayayım Serkan Bey. etiketler tablomuz şu şekilde olsun:
id,konuid,etiketler
Örneğin id=1, konuid=5 ve etiketler içeriği de şu şekilde olsun(etiketin türkçe hali ve karşılığındaki sef hali):
{“konuid”:5,”şablon”:“sablon”,”üşü”:“usu”,“tablo”:“tablo”,“masa”:“masa”,“dolap”:“dolap”}
Böyle bir durumda json_decode ile verileri dizi haline getirebiliriz sanırım.
peki “dolap” adlı etiketi kullanan yazıları listelemeniz gerektiğinde sizin tablo yapınızla nasıl listeleyeceksiniz ?
Onu da siz bulun artık hocam :) Uzman olan sizsiniz…
ahah :) ... Yazıdaki yöntemi kullanmamın bir nedeni de senin “onu da siz bulun” dediğin sorunu çözmek içindi. Böylece senin “Sizce bu sistemi fazlası ile yormaz mı? JSon olarak tüm etiketleri tek tabloda tutsanız daha mantıklı değil mi?” sorunu cevaplamış olduk :) ...
iyi çalışmalar.
Neyse sorunu çözmüş olmadınız,sadece yapılamayacağını iddia ettiniz. Bende diyorum ki anlattığım yöntem ile çözdüm. Size de kolay gelsin (: tesekkürler
peki :)
şeklinde mi diziye aktarıyoruz?
php yi yeni öğrenmeye başladım yardımcı olabilirmisiniz?
Şuna benzer birşey olacak.
yardımınız için teşekkür ederim.
paylaşım için teşekkürler çok faydalı bir yazı
merhabalar şimdi yazıyı okudum öncelikle harika yazı teşekkürler peki sormak istediğim şu yapmış olduğunuz örneği kullandığımızı farz edelim veritabanına yazıyı eklerken ayrıyetten etiketler tablosuna etiketlerimi yazdıracaz ? yazdırdık farz edelim etiketler tablosunda hangi yazıya ait olduğunu belirten birşey yok nasıl anlaşılcak yazıya ait etiketi listelemek istediğimizde. yada etikete tıklandığında verileri listelenmesi gerektiğinde.
Sırayla cevap vermeye çalışayım sorularınıza.
1 - yapmış olduğunuz örneği kullandığımızı farz edelim veritabanına yazıyı eklerken ayrıyetten etiketler tablosuna etiketlerimi yazdıracaz ?
öncelikle yazıya ait etiketleri “etiketler” tablosuna insert ediyoruz. Sonra etiketler tablosuna insert ettiğimiz etiketlerin id’si ve yazi id ile birlikte “yazi_etiket_iliskileri” tablosuna basacağız.
2 - yazdırdık farz edelim etiketler tablosunda hangi yazıya ait olduğunu belirten birşey yok nasıl anlaşılcak yazıya ait etiketi listelemek istediğimizde. yada etikete tıklandığında verileri listelenmesi gerektiğinde.
Bir yazının etiketlerini tutan tablomuz “etiketler” tablosu değil, “yazi_etiket_iliskileri” tablosudur. id si 5 olan yazıya ait etiketleri çeken sorgumuz şu şekilde olacak
3 id li etikete ait yazıları çeken sorgumuz :
Güzel yazı teşekkürler. Fakat aramayı nasıl yaptırıyoruz. Sitenizde sol tarafta etiket bulutu bloğu var ve buradan bir etikete tıkladığımız zaman ilgili haberler çıkıyor bunu nasıl yaptıracağım? Yardımcı olurmusunuz?
Bir önceki yorumda sorunuzun cevabını bulabilirsiniz….
Ben tam olarak onu demek istemedim Serkan Bey. İlgili etikete ait haberleri listeletmek istediğimizde arama yaptırmamız gerek bu durumda mysql like mı kullanacağız?
Doğru anladıysam eğer sorgunun şu şekilde olması gerekir.
Evet Serkan bey tam olarak söylemeye çalıştığım buydu. Hızlı ve net cevabınızdan ötürü teşekkür ederim.
Rica ederim. İyi çalışmalar.
Konuyla alakası yok ama birde şu benzer yazıları nasıl yapabiliriz sizin bloğunuzda üstte olan?
aynı etikete sahip yazıları çekerek yapabilirsiniz.
Birde şu etiket bulutunun php ve sql dosyalarını paylaşırmısınz rica etsem? Bir türlü çıkamadım işin içinden
Uygulama olarak hazırlamadım ya da hazırlamışsam bile şuan bulamadım. Konu içerisinde bütün kodların ne iş yaptığıyla beraber açık bir şekilde anlatmaya çalıştım. Adım adım ilerleyerek tekrar uygulamaya çalışın.
Örnek kısmını dikkatli incelerseniz bunun çalışmayacağını anlarsınız dizide hatalı yazım sözkonusu yanlış olan kısım:
teşekkür ederim uyarınız için. Örnek kullanımdaki yazım hatasını düzelttim.
haber istem için böyle bir sistem yapacağım anlatım iöin teşekkürler
Hocam ellerinize sağlık harika bir anlatım olmuş. Teşekkürler.