php MySQL إنشاء مُدوّنة

المدونة : إضافة التعاليق

آخر تحيين: 13-12-2015

sql JOIN : الربط بين الجداول تصحيح : إضافة المواضيع للمدونة


أظن أن العنوان يوحي لكم بما ينتظرنا في هذا الدّرس . سنُتيح لزوارنا إمكانية إبداء آراءهم حول كل موضوع من مواضيع المُدوّنة . و سنقوم بذلك في صفحة show.php . عندما ينتهي الزائر من قراءة الموضوع ، يمكنه التعليق عليه و إبداء ملاحظاته .
في النهاية ستكون لدينا صفحة show.php شبيهة بهذه .



سنحتاج إذاً ، إلى تطوير العمليات التالية :

  • إنشاء جدول في قاعدة البيانات لِتخزين بيانات التعاليق . سنسمّيه "blog_comments"
  • عرض التعاليق أسفل الموضوع في صفحة show.php
  • إضافة إستمارة التعاليق في صفحة show.php
  • صفحة مستقلّة لمعالجة و تخزين بيانات الإستمارة في القاعدة . سنسمّيها "add-comment.php"

كما جرت العادة ، المطلوب منك محاولة إنجاز التمرين قبل رؤية الحل.


إنشاء جدول التعاليق

لحد الآن ، في جميع الأمثلة التي رأيناها ، إعتدنا العمل على جدول واحد فقط في قاعدة البيانات . لكن غالبا ما نحتاج إلى مجموعة من الجداول ، و يزداد عددها كلّما أصبح موقعنا أكثر ثراء بوظائف جديدة . في النهاية بما أن الجداول تنتمي إلى نفس الموقع ، فيجب أن تربطها علاقة فيما بينها .
لنأخذ مثال جدولينا blog و blog_comments

  • blog : جدول مواضيع المدوّنة
  • blog_comments :جدول لحفظ تعاليق المواضيع

كل موضوع لديه تعاليقه الخاصة .أثناء عرضه يجب أن نعرض معه أيضاً التعاليق الخاصة به فقط . و ليس تعاليق المواضيع الأخرى . لمعرفة إلى أي موضوع ينتمي كل تعليق ، سنبين هذه العلاقة في جدول التعاليق blog_comments . و ذلك بإضافة حقل خاص برقم الموضوع الذي ينتمي إليه التعليق . و نُخزّن فيه غالبا مُعرّف "id" الموضوع .
إذاً ، عندما نريد تخزين التعليق في الجدول يجب أن نُخزّن معه أيضا رقم الموضوع الذي ينتمي إليه
و عندما نريد عرض التعاليق الخاصة بالموضوع ، سنعتمد على هذا الرقم :

SELECT * FROM blog_comments WHERE blog_id = 2 

الشيفرة تعني : "قُم باختيار تعاليق الموضوع رقم "2" من الجدول .
كفانا من النّظري ، لنبدأ في التطبيق و ننشيء جدولنا "blog_comments"، ستتضح لكم الأمور جيداً ، بعدها .

CREATE TABLE IF NOT EXISTS `blog_comments` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `author` varchar(40) NOT NULL,
  `content` text NOT NULL,
  `blog_id` int(11) NOT NULL,
  `creation_date` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;

كما تلاحظون ، حقل blog_id هو الذي سنُخزّن فيه رقم الموضوع . أمّا باقي الحقول فهي خاصة ببيانات التعليق .
بعد إنشاء الجدول ، دعوه جانبا .

عرض التعاليق

سنقوم بعرض التعاليق في صفحة show.php مُباشرة أسفل الموضوع . إستعلامنا سيعتمد على مُعرّف الموضوع الموجود في حقل blog_id :

$response = $db->prepare('SELECT id, author, content, creation_date
            FROM blog_comments
            WHERE blog_id = :id
           ');
$response->bindValue(':id', $blog_id, PDO::PARAM_INT);
$response->execute();
$comments = $response->fetchAll();
$response->CloseCursor();

ثم نقوم بعرض التعاليق
لا تنقلوا الشيفرات التي سترونها . حاولوا الفهم و في الأخير سأعطيكم شيفرات الصفحتين كاملة

$j = 0; 
if($response->rowCount() > 0) 
{
    echo '<div class="comments">';

    foreach($comments as $comment) 
    {
        $com_id = (int)$comment['id'];
        $com_author = htmlspecialchars($comment['author']);
        $com_content = nl2br(htmlspecialchars($comment['content']));
        $com_tari5 = htmlspecialchars($comment['creation_date']);

        $css_class = ($j % 2 == 1) ? 'odd black' : 'even orange'; // الشيفرة لها علاقة بالتنميق فقط
        ++$j;

        echo '
        <article class="'.$css_class .'">
            <div class="resume" id="comment-'.$com_id.'">
                <span>'.$com_author.'</span> <time class="details"> '.date("Y-m-d س i:H د",strtotime($com_tari5)).'</time>
                <a href="edit-comment.php?id='.$com_id.'" class="button orange"> تعديل </a> - 
                <a href="delete-comment.php?id='.$com_id.'" class="button red"> حذف </a>
            </div>
            <div class="comment">
               '.$com_content.'
            </div>
        </article>';
    }
    echo '</div>';
}
else 
{
    echo '<p class="errors"> لا يوجد أي تعليق ، كن أوّل من يفتتح النقاش !!!</p>';
}

لاحظوا أنني أضفت صفة class عبارة عن متغيّر : class="'.$css_class .'" هذا له علاقة بجانب التنميق اي css ، حتّى نتمكّن من تغيير أنماط الرّدود . ربّما تبدو لكم الشيفرة غريبة ، لكننا رأيناها سابقا .

$css_class = ($j % 2 == 1) ? 'odd' : 'even';

هذه الشيفرة هي إختزال للشيفرة أسفله

if($j % 2 == 1) { 
  $css_class = 'odd';
}else{
  $css_class= 'even';
}

الشيفرة تعني : إذا كان الباقي من قسمة رقم التعليق على 2 هو 1 ، أي أن العدد فردي . في هذه الحالة ، ستأخذ الصّفة class قيمة "odd" .

<div class="odd">

else : إذا كان باقي القسمة هو 0 . فإن العدد زوجي . و ستأخذ الصّفة class قيمة "even"

<div class="even">

و في صفحة css نقوم بإعطاء الأنماط التي نريدها لقيم الصفة class .

هناك نقطة تنظيمية أخرى ، و هي صفة "id" id="comment-'.$com_id.'" . هذه الصفة لها علاقة بالرابط المرساة . كما تعلمتم في لغة html ، فهو يُسهّل على الزّائر إيجاد مبتغاه بسهولة . في مثالنا ، عندما سيقوم الزائر بإضافة تعليقه بنجاح ، سنقوم بتحويله إلى صفحة مشاهدة التعاليق و سنُسقطه مباشرة على تعليقه ، بدل أن يقوم بالبحث عنه .
لهذا سنحتاج إلى رقم التعليق كقيمة للصفة "id"

إستمارة التعاليق

echo '
<form action="add-comment.php?id='.$blog_id.'" method="post">
  <label>الكاتب</label><input type="text" name="author"><br>
  <label>المحتوى</label><textarea name="content"></textarea>
  <p><input type="submit" value="إرسال"></p>
</form>';

في قيمة action وضعنا الرّابط إلى الصفحة التي ستعالج بيانات الإستمارة add-comment.php . دون أن ننسى رقم الموضوع "$blog_id" الذي سنضيف إليه التعليق


صفحة show.php كاملة

<?php
require 'includes/header.php';
require 'includes/db-connection.php';

// استقبال مفتاح الموضوع 
$blog_id = isset($_GET['id']) ? (int)$_GET['id']: 1;

// أخذ بيانات الموضوع من القاعدة ، إعتمادا على المفتاح
$response = $db->prepare('SELECT id, title, content, author, creation_date
            FROM blog 
            WHERE id = :bid
           ');
$response->bindValue(':bid', $blog_id, PDO::PARAM_INT);
$response->execute();
$blog = $response->fetch();
$response->CloseCursor();

// عرض بيانات الموضوع 
if($blog)
{
    $blog_title = htmlspecialchars($blog['title']);
    $blog_author = htmlspecialchars($blog['author']);
    $blog_content = nl2br(htmlspecialchars($blog['content']));
    $blog_tari5 = htmlspecialchars($blog['creation_date']);

    echo '
    <article class="blog">
    <h2>
        '.$blog_title.'
    </h2>
    <div class="details">
        <a href="edit-blog.php?id='.$blog_id.'" class="button orange"> تعديل </a> - 
        <a href="delete-blog.php?id='.$blog_id.'" class="button red"> حذف </a>
    </div>
	<hr>
    <div class="content">'.$blog_content.'</div>
    <div class="sidebar center">
        <span>الكاتب : '.$blog_author.'</span>
	    <time class="orange">'.date("Y-m-d س i:H", strtotime($blog_tari5)).'</time>
        <h3>مواضيع لنفس الكاتب</h3>
        <ul>
            <li><a href="#">كتمرين . يمكنك لاحقا عرض هنا ، روابط للمواضيع التي نشرها هذا الكاتب </a></li>
        </ul>
    </div>
    </article>
<hr>';
}else {
  die('لا يوجد أي موضوع !!! ');
}

// التعاليق
$response = $db->prepare('SELECT id, author, content, creation_date
            FROM blog_comments
            WHERE blog_id = :id
           ');
$response->bindValue(':id', $blog_id, PDO::PARAM_INT);
$response->execute();
$comments = $response->fetchAll();
$response->CloseCursor();

// عرض تعاليق الموضوع
echo '<h3 class="center"> التعاليق </h3>';
$j = 0; 
if($response->rowCount() > 0) 
{
    echo '<div class="comments">';

    foreach($comments as $comment) 
    {
        $com_id = (int)$comment['id'];
        $com_author = htmlspecialchars($comment['author']);
        $com_content = nl2br(htmlspecialchars($comment['content']));
        $com_tari5 = htmlspecialchars($comment['creation_date']);

        $css_class = ($j % 2 == 1) ? 'odd black' : 'even orange'; // الشيفرة لها علاقة بالتنميق فقط
        ++$j;

        echo '
        <article class="'.$css_class .'">
            <div class="resume" id="comment-'.$com_id.'">
                <span>'.$com_author.'</span> <time class="details"> '.date("Y-m-d س i:H د",strtotime($com_tari5)).'</time>
                <a href="edit-comment.php?id='.$com_id.'" class="button orange"> تعديل </a> - 
                <a href="delete-comment.php?id='.$com_id.'" class="button red"> حذف </a>
            </div>
            <div class="comment">
               '.$com_content.'
            </div>
        </article>';
    }
    echo '</div>';
}
else 
{
    echo '<p class="errors"> لا يوجد أي تعليق ، كن أوّل من يفتتح النقاش !!!</p>';
}

// إستمارة إضافة التعاليق
echo '<hr>
<form action="add-comment.php?id='.$blog_id.'" method="post" id="form">
  <fieldset class="form-item">
    <legend class="green">إضافة تعليق</legend>
    <label for="author"> الكاتب</label>
        <input type="text" name="author" id="author"><br>

    <label for="content">المحتوى</label>
    <textarea name="content" id="content"></textarea>
  </fieldset>

  <fieldset class="form-submit">
    <input type="submit" name="submit" value="إرسال" class="button green">
  </fieldset>
</form>
';
require 'includes/footer.php';
?>

صفحة add-comment.php كاملة

صفحة معالجة و تخزين التعاليق في القاعدة

<?php 
require 'includes/header.php';
require 'includes/db-connection.php';

$blog_id = isset($_GET['id']) ? (int)$_GET['id']: 0;

if(!empty($_POST['author']) && !empty($_POST['content']))
{
   $author = $_POST['author'];
   $content = $_POST['content'];
 
   // إدخال البيانات في القاعدة .
   $stmt= $db->prepare('INSERT INTO blog_comments ( content, author, blog_id, creation_date) 
                        VALUES (:cont, :auth, :bid, NOW())
                      ');
   $stmt->bindValue(':cont', $content, PDO::PARAM_STR);
   $stmt->bindValue(':auth', $author,  PDO::PARAM_STR);
   $stmt->bindValue(':bid',  $blog_id, PDO::PARAM_INT);
   $stmt->execute();
  
   $last_comment = $db->lastInsertId();
   $stmt->CloseCursor();

   header('location:show.php?id='.$blog_id .'#comment-'.$last_comment);
}
else 
{
    echo '<h2 class="error"> لم تملأ الإستمارة بشكل صحيح !!! </h2>';
}
require 'includes/footer.php';

عند إدخال التعليق في الجدول ، قمنا أيضاً بتخزين معرّف الموضوع الذي ينتمي إليه التعليق في حقل blog_id . كما ذكرنا سابقاً .
إستعملنا $db->lastInsertId() لأخذ رقم التعليق الذي أضفناه حتّى نوظّفه في الرّابط المرساة .


أترك لكم المجال لإنشاء صفحتي edit-comment.php و delete-comment.php . الأولى لتعديل التعليق و الثانية لحذفه .

في الدرس السابق كنا أنشأنا صفحة "delete-blog.php" لحذف الموضوع . يجب عليكم تعديل هذه الصفحة لحذف تعاليق الموضوع أيضا . إذ لا يصح أن نحذف الموضوع و نترك تعاليقه يتيمة في القاعدة .