v2.5.2
Giriş yap

Yorum Cevaplandırma

coder
324 defa görüntülendi

Merhaba arkadaşlar.

Bir makalemiz var.
Ona yorum yapılıyor. Ama yorum sisteminde kişiler, bir yorum altında bir birine cevap verebiliyor.
Aşağıdaki resimde olduğu gibi.

Şimdi bunu yapabilmem için şunlar olması gerekiyor.

makaleler tablosu
makale_id | makale_icerik

uyeler tablosu
uye_id | uye_adi

yorumlar tablosu
yorum_id | makale_id | uye_id | yorum_icerik

Şimdi takıldığım nokta şu.

Bir yorum altında kişileri nasıl birbirine cevap verdirebilirim.
Tablo yapısı nasıl olmalı?

ebykdrms
296 gün önce

Üst Not: @fatihkurtl benden önce cevap vermiş. Benim cevabım biraz daha farklı oldu. Her yiğidin yoğurt yiyişi farklı tabi. :) Aşağıda benim kendimce cevabım var:

~ Kişi makale oku linkine tıkladığında html sayfasını mı görecek?
~ Evet. Direkt html sayfasını görmeli. PHP'ye hiç iş ilişmemeli. Veritabanını meşgul etmemeli. Çünkü makaleler sürekli güncellenen, anlık işleme girmesi gereken içerik değildirler. Mesela bir e-ticaret sitesinde ürün detay sayfaları da böyledir. Buralarda nadiren yapılan güncellemeler olur. Bu durumda da yeni bir cache dosyası oluşturulur. Ama mesela kullanıcının sepeti, anlık olarak işlem görmesi gereken, hassas bir yerdir. Mutlaka veritabanından kontrolü gerekir.

~ HTML sayfası PHP sayfasına include mu edilecek?
~ Hayır. HTML sayfası direkt bir dosya olarak oluşturulmalı ve mesela FTP'yle sunucudaki dosyalarınıza baktığınızda html uzantılı bir dosya olarak görülebilmeli. PHP olmasa bile kendi başına çalışabilir bir dosya olmalı. Böyle bir çıktıyı nasıl üretebileceğinizi şimdilik geçiyorum ama aslında zor değil. Sayfayı oluşturdunuz diyelim. Bu sayfaya yönlendirme işlemi PHP .htaccess dosyası ile sağlanabilir. Dosyanın adı aslında url'deki adıdır. Mesela yapay-zekanin-yukselisi.html adlı bir dosya. .htaccess dosyasında uygun bir yönlendirmeyle kullanıcının bu sayfaya http://siteadi.com/makale/yapay-zekanin-yukselisi url'siyle ulaşması sağlanmalı.
Örneğin bu dosyaları yönetim panelinden düzenledikten sonra /makaleler adlı bir klasöre PHP yardımıyla kaydettiniz. Şu an /makaleler/yapay-zekanin-yukselisi.html diye bir dosyanız var. Bu dosyaya, http://siteadi.com/makale/yapay-zekanin-yukselisi linki ile ulaşılabilsin istiyorsunuz.
Sitenizin kök klasöründeki .htaccess dosyasında şu şekilde yönlendirme sağlayabilirsiniz:

RewriteEngine On
RewriteRule ^makale/(.+)/?$ /makaleler/$1.html [L,R=301]

Bu sayede kullanıcı http://siteadi.com/makale/yapay-zekanin-yukselisi url'sini çağırırsa sunucu tarafından direkt /makaleler/yapay-zekanin-yukselisi.html dosyasına yönlendirilir.
Tabi CodeIgniter, Laravel gibi framework'ler kullanıyorsanız bu cache mekanizmasının framework'ler içinde kendi çözümleri var.

~ Her makalenin html dosyası olmalı mı?
~ Evet. Her makalenin bir html dosyası olmalı. Tabi binlerce makale olduğunda bu sistemi de optimize etmek gerekir. Bu çok daha detaylı bir konu.

Elbette küçük çaplı projelerde bu kadar optimizasyona gerek yok. Anlık kullanıcı sayısının çok artabileceği, sunucunun isteklere yetişemeyebileceği projeler için tüm bunlar yapılmalı ama zaten anlık 10-15 kullanıcıdan yukarı pek çıkmayan bir proje için bu kadar uğraşmak gerekmez.

Aldığınız hata: foreach() argument must be of type array|object, bool given in ... on line 70
Yani 70. satırda foreach, array veya object değeri ararken bool değerle karşılaşmış.
Muhtemelen 70. satır dediği yer sizin <?php foreach($ust_yorumlar as $ust_yorum): ?> satırınıza denk geliyordur.
Buna göre sanırım 67. satırınıza denk gelen $ust_yorumlar = yorumlar($mak_id, $ust_yorum_id); satırınızda $ust_yorumlar değişkeninize false değeri atanıyor olabilir.

Ama genel olarak kurgunuzda bir sorun var. foreach döngüsü içinde yorumlar() fonksiyonunu çağırmamalısınız. Bu fonksiyon veritabanına istek atıyor. Bu durumda dönünün her adımında veritabanı isteği atmış oluyorsunuz.
Çözüm olarak, makaleye ait tüm yorumları tek seferde çekmelisiniz ve PHP ile bir obje oluşturarak bu yorumların hiyerarşisini düzenlemelisiniz.
Yani mesela "SELECT * FROM yorumlar INNER JOIN uyeler ON uyeler.uye_id = yorumlar.uye_id WHERE makale_id = :mak_id"; şeklinde tüm yorumları tek seferde veren tek bir sorgu.
Bu sorgunun sonucu $yorumlar değişkenine aldınız varsayalım. Sonrasında mesela $duzenlenmisYorumlar adlı boş bir dizi oluşturup, $yorumlar dizinizde dolaşarak gerekli hiyerarşide yorumlarınızı yeni diziye aktarabilirsiniz.

<?php
$yorumlar = tumYorumlar($mak_id);
$duzenlenmisYorumlar = [];
foreach($yorumlar as $yorum) {
    // Baktığımız yorumun üst yorumu yoksa, ana yorum olarak eklensin.
    if($yorum['ust_yorum_id'] === 0) {
      $duzenlenmisYorumlar[ 'yorum_'.$yorum['yorum_id'] ] = ['yorum'=>$yorum, 'alt_yorumlar'=>[]];
    }
    // Baktığımız yorumun üst yorumu varsa, o yorumun alt yorumu olarak eklensin
    else {
      $duzenlenmisYorumlar[ 'yorum_'.$yorum['yorum_id'] ]['alt_yorumlar'][] = $yorum;
    }
}
?>

Artık foreach ile dolaşıp yorumları dom'a basabilirsiniz.

<?php foreach($duzenlenmisYorumlar as $key=>$data) { ?>
    <div class="ana_yorum" data-key="<?= $key ?>">
        <div><?= $data['yorum']['yorum_adi'] ?></div>
        <div><?= $data['yorum']['yorum_icerik'] ?></div>
        <a href="#" class="mt-2">Cevapla</a>
        <?php foreach($data['alt_yorumlar'] as $altYorum) { ?>
            <div class="cevap_yorum">
                <div><?= $altYorum['yorum_adi'] ?></div>
                <div><?= $altYorum['yorum_icerik'] ?></div>
                <a href="#" class="mt-2">Cevapla</a>
            </div>
        <?php } ?>
    </div>
<?php } ?>

Uzun zamandır PHP kullanmıyorum. Yukarıdaki kodları test etmeden yazdım. Yani hatalı olabilir. Ama kurgusal olarak ne yapmaya çalıştığımı aşağı yukarı belli ediyordur.

Not: PHP'de string ifade belirtirken çift tırnak " ve tek tırnak ' farklı amaçlarla kullanılır.
Eğer string ifade içinde değişken kullanmayacaksanız (Örn: "Benim adım $isim. Seninki ne?") tek tırnak kullanmalısınız. Çünkü PHP, çift tırnak içinde bir değişken olabileceğini varsayar. Ama tek tırnak içinde değişken aramaz. Çok çok küçük bir performans maliyeti olsa da, büyük çaplı projeler için milisaniyeler bile önemli olduğundan, alışkanlık kazanmak iyi olur.

Not: Yanlış anlamayın, bu notları size özel yazmıyorum. Ben cevaplarımda, herkesin okuyabileceğini düşünerek böyle detaylar paylaşıyorum. :)