version 4.1.0

ตัวอย่างระบบแสดงความคิดเห็นด้วย ajax

  อังคารที่ 27 มกราคม พ.ศ. 2558 เวลา 08:58:30 น.      2,959 ครั้ง


ตัวอย่างระบบแสดงความคิดเห็นด้วย ajax

แนะนำ

บทเรียนนี้ เราจะมาศึกษาวิธีการสร้างระบบแสดงความคิดเห็น + เทคนิค AJAX เข้ามาร่วมด้วย โดยตัวระบบนี้จะมีความสามารถที่ไม่เหมือนกับระบบแสดงความคิดเห็นทั่ว ๆ ไป ที่ทำการผูกติดระบบเข้ากับหน้าที่ต้องการเปิดให้มีการสามารถคิดเห็นได้ ซึ่งตัวระบบนี้นั้นได้ "ถูกออกแบบ" โดยจะแบ่งแยกตัวการทำงานของระบบออกเป็นเหมือน Extension ย่อย ที่เราสามารถเรียกใช้งานได้จากหน้าไหนก็ได้ ภายในเว็บไซต์นั้น ๆ ได้เลย ช่วยให้ง่ายต่อการจัดการเป็นอย่างมาก ได้เวลาละ มาเริ่มต้นกันเลยครับ..

บทนี้มีอะไรบ้าง

  1. ตอนที่ 1 เตรียมความพร้อมก่อนเริ่มต้นพัฒนาระบบ
  2. ตอนที่ 2 ตั้งค่าให้กับระบบแสดงความคิดเห็น ในไฟล์ Config
  3. ตอนที่ 3 เขียนคำสั่งลงในส่วนของ Comment Module
  4. ตอนที่ 4 เขียนคำสั่งลงไฟล์ในส่วนของ Behaviors
  5. ตอนที่ 5 เขียนคำสั่งลงในส่วนของ Comment Controller
  6. ตอนที่ 6 เขียนคำสั่งในส่วนของ View ทั้งหมด
  7. ตอนที่ 7 สร้างระบบแสดง Profile สำหรับพูกระบบคอมเม้นลงไป
  8. ตอนที่ 8 การเพิ่มเติมคำสั่งระบบแสดงความคิดเห็น
  9. ตอนที่ 9 ทดสอบการทำงาน "ระบบแสดงความคิดเห็น"

สร้างตารางฐานข้อมูล ชื่อว่า "tbl_comments"

 CREATE TABLE IF NOT EXISTS `tbl_comments` (
  `id`         int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `message`    text COLLATE utf8_unicode_ci,
  `userId`     int(11) UNSIGNED DEFAULT NULL,
  `createDate` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

สร้างไฟล์ Model ชื่อว่า "Comment.php" และเขียนคำสั่งตามตัวอย่างด้านล่างนี้ โดยเก็บไว้ในไดเรคทอรี่ [skeleton]\protected\models\

เขียนคำสั่งลงในไฟล์ Comment.php ในโฟล์เดอร์ models

 // in model
class Comment extends CActiveRecord
{

    public function tableName()
    {
        return 'tbl_comments';
    }

    public function rules()
    {
        return array(
            array('message', 'safe'),
            array('id, message, userId', 'safe', 'on' => 'search'),
        );
    }
    
    public function attributeLabels()
    {
        return array(
            'id' => 'ID',
            'message' => 'Message',
            'userId' => 'User ID',
        );
    }

    public function search()
    {
        $criteria = new CDbCriteria;
        $criteria->compare('id', $this->id);
        $criteria->compare('message', $this->message,true);
        $criteria->compare('userId', $this->userId);
        return new CActiveDataProvider($this, array(
            'criteria' => $criteria,
        ));
    }
    
    public static function model($className = __CLASS__)
    {
        return parent::model($className);
    }
    
    public function getUserName()
    {
        return is_null(Yii::app()->user->id) ? 'Guest' : Yii::app()->user->name;
    }
        
}

จากนั้น สร้างโฟล์เดอร์และไฟล์ ตามโครงสร้างระบบตัวอย่าง ด้านล่างนี้

สร้างโฟล์เดอร์และไฟล์ตามโครงสร้างต่อไปนี้ (สร้างทิ้งไว้ก่อน) ลงในโฟล์เดอร์ extensions

  • extensions
  • -- | comment
  • -- | -- | behaviors
  • -- | -- | -- | CommentableBehavior.php
  • -- | -- | controllers
  • -- | -- | -- | CommentController.php
  • -- | -- | models
  • -- | -- | -- | Comment.php (สร้างทีหลัง)
  • -- | -- | views
  • -- | -- | -- | comment
  • -- | -- | -- | -- | _form.php
  • -- | -- | -- | -- | _view.php
  • -- | -- | -- | -- | commentList.php
  • -- | -- | CommentModule.php

รูปภาพตัวอย่าง

รูปภาพตัวอย่าง

รูปภาพที่ 1 | รูปภาพตัวอย่าง

เพียงเท่านี้ เราก็ไปเขียนคำสั่งให้ระบบมันสามารถทำงานได้แล้ว



ตั้งค่า Config สำหรับเรียกใช้งาน Comment Extension

 // in config (main.php)
array(
    'modules' => array(
        .....
        'comment' => array(
            'class' => 'ext.comment.CommentModule',
        ),
    )
),


เพิ่มเติมคำสั่งลงในไฟล์ Module ชื่อว่า CommentModule.php

 // in modules
class CommentModule extends CWebModule
{

    public $commentableModels = array();
    
    // alias path : Comment Model
    public $commentModelClass = 'comment.models.Comment';      
    
    public function init()
    {
        $this->setImport(array(
            'comment.models.*',
            'comment.behaviors.*',
        ));
    }
    
    public function beforeControllerAction($controller, $action)
    {
        if(parent::beforeControllerAction($controller, $action))
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    
}


เขียนคำสั่งในไฟล์ CommentableBehavior.php ในโฟล์เดอร์ behaviors

 // in behaviors (CommentableBehavior.php)
class CommentableBehavior extends CActiveRecordBehavior
{

    public function getCommentDataProvider()
    {
        // Comment ชื่อ Comment Model
        return new CActiveDataProvider('Comment');
    }
    
    public function getCommentInstance()
    {
        return Yii::createComponent($this->module->commentModelClass);
    }
    
    public function getModule()
    {
        // ดึงข้อมูลจาก Comment Model
        return Yii::app()->getModule('comment');
    }
    
}


เขียนคำสั่งลงในไฟล์ CommentController.php ในโฟล์เดอร์ controllers

 // in controller 
class CommentController extends CController
{
    
    public function actionCreate()
    {
        /* เขียนคำสั่ง */
    }
    
    public function actionUpdate($id)
    {
        /* เขียนคำสั่ง */
    }
    
    public function actionDelete($id)
    {
        /* เขียนคำสั่ง */
    }
    
    public function loadModel($id)
    {
        $model = Yii::createComponent($this->module->commentModelClass)->findByPk((int) $id);
        if ($model === null) {
            throw new CHttpException(404, 'The requested page does not exist.');
        }
        return $model;
    }
    
    protected function performAjaxValidation($model)
    {
        if(isset($_POST['ajax']) && $_POST['ajax'] === 'comment-form')
        {
            echo CActiveForm::validate($model);
            Yii::app()->end();
        }
    }

}

เขียนคำสั่งในการทำงาน สำหรับ "เพิ่มความคิดเห็นใหม่" ในส่วนของ actionCreate()

"เพิ่มความคิดเห็นใหม่" ในส่วนของ actionCreate()

 // in CommentController.php
public function actionCreate()
{

    $model = Yii::createComponent($this->module->commentModelClass);
    
    // เปิดกรณีต้องการใช้ AJAX ในการกรอกข้อมูล
    // $this->performAjaxValidation($model);
    
    if(isset($_POST[$cClass = get_class($model)]))
    {
    
        $model->attributes = $_POST[$cClass];
            
        // ตรวจสอบข้อมูลการเข้าสู่ระบบ
        if (Yii::app()->user->isGuest) 
        {
            $model->userId = null;
        } 
        else 
        {
            $model->userId = Yii::app()->user->id;
        }
        
        $model->createDate = date('Y-m-d H:i:s', time());
    
        // ตรวจสอบคำร้องขอจาก AJAX
        if(Yii::app()->request->isAjaxRequest) 
        {
        
            $output = '';
            
            // ตรวจสอบการบันทึกข้อมูล
            if($model->save())
            {
                $model->refresh();
                
                $output .= $this->renderPartial('_view', array(
                    'data' => $model,
                ), true);
                
                $model = Yii::createComponent($this->module->commentModelClass);
            }
            
            $output .= $this->renderPartial('_form', array(
                'comment' => $model,
                'ajaxId' => time(),
            ), true);
            
            // render javascript functions
            Yii::app()->clientScript->renderBodyEnd($output);
            
            // แสดงข้อมูล "คอมเม้น" ล่าสุด
            echo $output;
            Yii::app()->end();
        } 
        else 
        {
            if($model->save()) 
            {
                $this->redirect(isset($_POST['returnUrl']) ? 
                    $_POST['returnUrl'] : array('view', 'id' => $model->id));
            } 
            else 
            {
                // @todo: what if save fails?
            }
        }
    }
}

เขียนคำสั่งในการทำงาน สำหรับ "แก้ไขความคิดเห็น" ในส่วนของ actionUpdate()

"แก้ไขความคิดเห็น" ในส่วนของ actionUpdate()

 // in CommentController.php
public function actionUpdate($id)
{

    // โหลดข้อมูล
    $model = $this->loadModel($id);
    
    if(isset($_POST[$cClass = get_class($model)]))
    {
    
        $model->attributes = $_POST[$cClass];
        
        // ตรวจสอบการบันทึกข้อมูล
        if ($model->save())
        {
        
            // ตรวจสอบคำร้องขอจาก AJAX
            if(Yii::app()->request->isAjaxRequest) {
            
                $model->refresh();
                
                // render updated comment
                $this->renderPartial('_view', array(
                    'data' => $model,
                ));
                
                Yii::app()->end();
            } 
            else 
            {
                $this->redirect(isset($_POST['returnUrl']) ? 
                    $_POST['returnUrl'] : array('view', 'id' => $model->id));
            }
        }
    }
    
    // ตรวจสอบคำร้องขอจาก AJAX
    if(Yii::app()->request->isAjaxRequest)
    {
        $output = $this->renderPartial('_form', array(
            'comment' => $model,
            'ajaxId' => time(),
        ), true);
        
        // render javascript functions
        Yii::app()->clientScript->renderBodyEnd($output);
        
        // แสดงข้อมูล "คอมเม้น" ล่าสุด
        echo $output;
        Yii::app()->end();
    }
}

เขียนคำสั่งในการทำงาน สำหรับ "ลบความคิดเห็น" ในส่วนของ actionDelete()

"ลบความคิดเห็น" ในส่วนของ actionDelete()

 // in CommentController.php
public function actionDelete($id)
{

    // ตรวจสอบคำร้องขอจาก AJAX
    if(Yii::app()->request->isPostRequest)
    {
    
        // โหลดข้อมูล
        $model = $this->loadModel($id);
        if (!Yii::app()->user->isGuest)
        {
            $model->delete();
            // if AJAX request
            if (!Yii::app()->request->isAjaxRequest) {
                $this->redirect(isset($_POST['returnUrl']) ? 
                    $_POST['returnUrl'] : array('admin'));
            }
        }
        
    }
    
}


เขียนคำสั่งลงในไฟล์ commentList.php ในโฟล์เดอร์ views\comment

 // in commentList.php
<?php
    $comments = $model->getCommentDataProvider();
?>

<div class="row" style="padding:10px;">

    <!-- แสดงรายการแสดงความคิดเห็น -->
    <?php $this->widget('zii.widgets.CListView', array(
        'dataProvider' => $comments,
        'itemView' => 'comment.views.comment._view'
    )); ?>
    
    <!-- แสดงฟอร์มรับข้อมูล ความคิดเห็น -->
    <?php $this->renderPartial('comment.views.comment._form', array(
	'comment' => $model->commentInstance
    )); ?>
    
</div>

ไฟล์นี้ที่ใช้สำหรับ "แสดงรายการ" ในแต่ละรายการแสดงความคิดเห็น

เขียนคำสั่งลงในไฟล์ _view.php ในโฟล์เดอร์ views\comment

 // in _view.php
<?php
    // แทรกคำสั่ง CSS
    Yii::app()->clientScript->registerCss('ext-comment', "
        div.ext-comment { width:100%; margin:25px auto; }
        div.ext-comment hr { margin:0; padding:0; border:none; border-bottom:solid 1px #AAA; }
        span.ext-comment-name { font-weight:bold; }
        span.ext-comment-head { color:#AAA; }
        span.ext-comment-options { float:right; color:#AAA; }
    ");
?>

<div class="col-md-12" style="padding:10px;">
    <div class="ext-comment" id="ext-comment-<?php echo $data->id; ?>">
        <span class="ext-comment-options">
        
            <?php 
                if (!Yii::app()->user->isGuest) {
                
                    // แสดงปุ่ม "ลบความคิดเห็น"
                    echo CHtml::ajaxLink('delete', array(
                        '/comment/comment/delete', 'id' => $data->id), 
                    array(
                        'success' => 'function(){ $("#ext-comment-' . $data->id . '").remove();}',
                        'type' => 'POST',
                    ), 
                    array('id' => 'delete-comment-' . $data->id, 
                        'confirm' => 'คุณต้องการลบความคิดเห็นนี้ [ใช่หรือไม่] ?')
                );
                
                echo " | ";   
                
                // แสดงปุ่ม "แก้ไขความคิดเห็น"
                echo CHtml::ajaxLink('edit', array('/comment/comment/update', 'id' => $data->id), 
                    array('replace' => '#ext-comment-' . $data->id, 'type' => 'GET'), 
                    array('id' => 'ext-comment-edit-' . $data->id)
                );
            } 
        ?>
    </span>
    
        <!-- แสดงข้อความที่แสดงความคิดเห็น -->
        <p><?php echo nl2br(CHtml::encode($data->message)); ?></p>
        
        <!-- แสดงข้อมูลผู้ที่เข้ามาแสดงความคิดเห็น -->
        <span class="ext-comment-head">
            Author <span class="ext-comment-name"><?php echo CHtml::encode($data->userName); ?></span> 
            Create At : <?php echo $data->createDate; ?>
        </span>
        
        <br style="clear: both;" />
        
    </div>
</div>

ไฟล์นี้ ใช้สำหรับการแสดง "ฟอร์มรับข้อมูลแสดงความคิดเห็น"

เขียนคำสั่งลงในไฟล์ _form.php ในโฟล์เดอร์ views\comment

 // in _form.php
<div class="col-md-12" >

    <?php if (Yii::app()->user->isGuest): ?>
        <div style="margin-top:15px;">Sorry, you have to login to leave a comment.</div>
    <?php else: ?>
    
        <div id="ext-comment-form-<?php echo $comment->isNewRecord ? 
            'new' : 'edit-' . $comment->id; ?>" class="form">
        
            <?php $form = $this->beginWidget('CActiveForm', array(
                'id' => 'ext-comment-form',
                'action' => array('/comment/comment/create'),
                'enableAjaxValidation' => false,
            )); ?>
            
            <?php echo $form->errorSummary($comment); ?>
            
            <?php echo $form->labelEx($comment, 'message'); ?>
            <?php echo $form->textArea($comment, 'message', array('rows' => 3, 'cols' => 50)); ?>
            <?php echo $form->error($comment, 'message'); ?>
            
            <?php if ($comment->isNewRecord): ?> 
                <?php echo CHtml::ajaxSubmitButton('Submit', array('/comment/comment/create'), 
                    array(
                        'replace' => '#ext-comment-form-new',
                        'error' => "function(){
                            $('#Comment_message').css('border-color', 'red');
                            $('#Comment_message').css('background-color', '#fcc');
                        }"
                    ),
                    array('id' => 'ext-comment-submit' . (isset($ajaxId) ? $ajaxId : ''))
                ); ?>
            <?php else: ?>
                <?php echo CHtml::ajaxSubmitButton('Update',array(
                        '/comment/comment/update', 'id' => $comment->id
                    ),
                    array(
                        'replace' => '#ext-comment-form-edit-' . $comment->id,
                        'error' => "function(){
                            $('#Comment_message').css('border-color', 'red');
                            $('#Comment_message').css('background-color', '#fcc');
                        }"
                    ),
                    array('id' => 'ext-comment-submit' . (isset($ajaxId) ? $ajaxId : ''))
	        ); ?>
            <?php endif; ?>
            
            <?php $this->endWidget() ?>
        </div>
        
    <?php endif; ?>
</div> 


สร้างตาราง ชื่อว่า "tbl_profile"

 CREATE TABLE IF NOT EXISTS `tbl_profile` (
  `user_id` int(11) NOT NULL AUTO_INCREMENT,
  `lastname` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  `firstname` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1;

1. สร้างตารางชื่อว่า "tbl_profile" ด้วยคำสั่ง SQL ด้านบนนี้

เพิ่มข้อมูลลงตาราง ชื่อว่า "tbl_profile"

 
INSERT INTO `tbl_profile` (`user_id`, `lastname`, `firstname`) VALUES
(1, 'Admin', 'Administrator'),
(2, 'Demo', 'Demo'),
(3, 'Test', 'Test');

2. เพิ่มข้อมูลที่ใช้สำหรับการทดสอบลงไปในตาราง "tbl_profile" ด้วยคำสั่ง SQL ด้านบนนี้

รูปภาพตัวอย่าง

รูปภาพตัวอย่าง

รูปภาพที่ 2 | รูปภาพตัวอย่าง

3. สร้างไฟล์ Model ชื่อว่า "Profile.php" ด้วย Gii System และย้ายไฟล์ไปไว้ในโฟล์เดอร์ models ใน extensions\comment\models\Profile.php

คำสั่งในไฟล์ "ProfileController.php"

 class ProfileController extends Controller
{

    public function actionIndex()
    {
        $model = new Profile('search');
        $model->unsetAttributes();  // clear any default values
        if(isset($_GET['Profile']))
            $model->attributes = $_GET['Profile'];
        
        $this->render('index', array(
            'model' => $model,
        ));
    }

}

4. สร้างไฟล์ Controller ชื่อว่า "ProfileController.php" และเขียนคำสั่งด้านบนนี้ลงไป

สร้างไฟล์ views ชื่อว่า "index.php"

 <?php
    $this->breadcrumbs = array(
        'Profiles' => array('index'), 'Manage',
    );
?>

<h1>Manage Profiles</h1>

<?php 
    $this->widget('zii.widgets.grid.CGridView', array(
        'id' => 'profile-grid',
        'dataProvider' => $model->search(),
        'filter' => $model,
        'columns' => array(
            'user_id',
            'lastname',
            'firstname',
            array(
                'class' => 'CButtonColumn',
            ),
        ),
    )); 
?>

5. สร้างไฟล์ views ชื่อว่า "index.php" เขียนคำสั่งตามตัวอย่างลงไป ในภายโฟล์เดอร์ "views\profile\index.php"



แทรกคำสั่ง Method behaviors() ลงภายใน Model ที่เราต้องการ

 // in Model (Profile Model)
class Profile extends CActiveRecord
{
    /* ..... */
    public function behaviors() {
        return array(
            'commentable' => array(
                'class' => 'ext.comment.behaviors.CommentableBehavior',
            ),
       );
    }

}

ขั้นตอนสุดท้าย แทรกคำสั่งต่อไปนี้ ลงในส่วนที่เราต้องการแสดงความคิดเห็น เช่น หน้าล่างสุดของหน้าแสดงรายละเอียด เป็นต้น

คำสั่งตัวอย่าง "แสดงความคิดเห็น"

 // in view
<div class="col-lg-12" style="border:1px solid #CCC;margin:35px 15px 0px 15px;width:95%;padding:10px;">
    <h1>Comment</h1>
    <?php $this->renderPartial('comment.views.comment.commentList', array(
        'model' => $model,
    )); ?>
</div>

แทรกคำสั่งด้านบนลงไปในไฟล์ views ชื่อว่า "index.php" เป็นอันเสร็จเรียบร้อยแล้ว.. เตรียมไปทดสอบกันเลยครับ..



กรณี ยังไม่ได้ล๊อกอินเข้าสู่ระบบ

กรณี ยังไม่ได้ล๊อกอินเข้าสู่ระบบ

รูปภาพที่ 3 | กรณี ยังไม่ได้ล๊อกอินเข้าสู่ระบบ

หากเรา ยังไม่ได้ล๊อกอินเข้าสู่ระบบ ระบบจะแสดงข้อความว่า "Sorry, you have to login to leave a comment." ดังภาพด้านบนออกมา

กรณี ล๊อกอินเข้าสู่ระบบแล้ว

กรณี ล๊อกอินเข้าสู่ระบบแล้ว

รูปภาพที่ 4 | กรณี ล๊อกอินเข้าสู่ระบบแล้ว

หาก เราล๊อกอินเข้าสู่ระบบแล้ว ระบบจะแสดง "ฟอร์มรับข้อมูลแสดงความเห็น" ดังภาพด้านบนออกมา

ทดสอบ "แสดงความคิดเห็น"

ทดสอบ

รูปภาพที่ 5 | ทดสอบ "แสดงความคิดเห็น"

ทดสอบ "แสดงความคิดเห็น" ประมาณ 3 - 5 รายการขั้นไป ดังภาพด้านบนนี้

ทดสอบ "แก้ไขความคิดเห็น"

ทดสอบ

รูปภาพที่ 6 | ทดสอบ "แก้ไขความคิดเห็น"

ทดสอบ "แก้ไขความคิดเห็น" คอมเม้น Comment 1 โดยกดทีปุ่ม edit ตรง แถวนั้น ๆ จากนั้น แทรกข้อความ "Edit" ต่อท้าย และกดปุ่ม Update

ทดสอบ "แก้ไขความคิดเห็น"

ทดสอบ

รูปภาพที่ 7 | ทดสอบ "แก้ไขความคิดเห็น"

หลังการแก้ไข "ความคิดเห็น" ของคอมเม้น Comment 1 แสดงผลลัพธ์ดังรูปด้านบน

ทดสอบ "ลบความคิดเห็น"

ทดสอบ

รูปภาพที่ 8 | ทดสอบ "ลบความคิดเห็น"

ทดสอบ "ลบความคิดเห็น" ของคอมเม้น Comment 1 Edit แสดงผลลัพธ์ดังรูปด้านบน

ทดสอบ "ลบความคิดเห็น"

ทดสอบ

รูปภาพที่ 9 | ทดสอบ "ลบความคิดเห็น"

หลังลบ "ความคิดเห็น" ของคอมเม้น Comment 1 Edit แสดงผลลัพธ์ดังรูปด้านบน

ภาพรวมทั้งหมด

ภาพรวมทั้งหมด

รูปภาพที่ 10 | ภาพรวมทั้งหมด



แท็ก


นักแปล / นักเขียน / เรียบเรียง

author

เอกบิณ ใจแก้วมา (แม็ก)

"โปรแกรมเมอร์ตัวเล็ก ๆ" สะสมประสบการณ์ด้านการพัฒนาซอฟแวร์มามากกว่า 11 ปี
# ติดตามผลงานได้ที่ | พบกับเราที่ Google+ | Facebook






Comment