Cakephp:多模型评论系统

时间:2011-07-27 01:14:26

标签: php cakephp pagination

我正在使用cakephp,我有一个带有两个字段的模型“comment”:“model_type”和“model_id”,以便评论我的应用程序的每个项目(例如图片,新闻,文章......)单一评论模型。

我想知道如何做到这一点。 (可以评论的控制器的组件“注释”?)

最后,我想在一个帮助器中列出评论: $ comment-> show('model_name','item_id'); 这将显示正确的分页注释和用于向项添加新注释的表单。

感谢。

3 个答案:

答案 0 :(得分:5)

修改:也请看这个:http://bakery.cakephp.org/articles/AD7six/2008/03/13/polymorphic-behavior

解决方案

多模型评论系统和分页只需:

<?php echo $this->element('comments', 
    array(
        'model_type' => "model_name", 
        'model_id' => $data['model']['id'],
        'order_field' => 'created',
        'order' => 'asc')); ?>

模型

计划:

- id
- model_type
- model_id
- content
(optional:)
- user_id
- created
- updated
- rating
- ...

评论模型:


// {app}/models/comment.php
class Comment extends AppModel{
    public $name = 'Comment';

    // List of model that could be commented
    protected $model_list = array(
        'news' => array(
            'name' => 'News', // here it's the model's name
            'field' => 'validated'), // A field for validation ( allow comments only on validaded items)
        'articles' => array(
            'name' => 'Article',
            'field' => 'validated')
    );

        // This is an example
    public $belongsTo = array( 
        'User' => array(
            'conditions' => 'User.validated = true'
            )
        );

    public $validate = array(
        'model_type' => array(
            'rule' => 'checkModelType',
            'message' => "Something goes wrong !"
        ),
        'model_id' => array(
            'rule' => 'checkModelId',
            'message' => "Something goes wrong !"
        ),
        'content' => array(
             'rule' => 'notEmpty',        
             'message' => "Empty content !"
         )
    );

        // Check if the model is commentable
    public function checkModelType($data){
        $model_type = $data['model_type'];
        return in_array($model_type, array_keys($this->model_list));
    }

        // Check if the item exists and is validated
    public function checkModelId($data){
        $model_id = intval($data['model_id']);

        $model = $this->model_list[$this->data['Comment']['model_type']];

        $params = array(
            'fields' => array('id', $model['field']),
            'conditions' => array(
                $model['name'].'.'.$model['field'] => 1, // Validated item
                $model['name'].'.id' => $model_id
                )
        );

                // Binding model to Comment Model since there is no $belongsTo
        return (bool) ClassRegistry::init($model['name'])->find('first', $params);
    }
}

控制器


// {app}/controllers/comments_controller.php
class CommentsController extends AppController
{
    public $name = 'Comments';

        // Pagination works fine !
    public $paginate = array(
        'limit' => 15,
        'order' => array(            
            'Comment.created' => 'asc')    
        );

    // The action that lists comments for a specific item (plus pagination and order !)
    public function view($model_type, $model_id, $order_field = 'created', $order = 'DESC'){
        $conditions = array(
                'Comment.model_type' => $model_type, 
                'Comment.model_id' => $model_id
                );

                // (optional)
        if($order_field != 'created') {
            $this->paginate['order'] = array(
                'Comment.'.$order_field => $order,
                'Comment.created' => 'asc');
        }

                // Paginate comments
        $comments = $this->paginate($conditions);

                // This allow to use paginator with requestAction
        $paginator = ClassRegistry::getObject('view')->loaded['paginator'];
        $paginator->params = $this->params;
        return compact('comments', 'paginator');
    }

    public function add(){
        // What you want !
    }
}

观点

评论元素

/* {app}/views/elements/comments.ctp
@params : $model_type
*   : $model_id
* 
* */

$result = $this->requestAction("/comments/view/$model_type/$model_id/$order_field/$order/", $this->passedArgs);
$paginator = $result['paginator'];
$comments = $result['comments'];

$paginator->options(array('url' => $this->passedArgs));
?>
<h2>Comments</h2>

<fieldset class="commentform">
<legend>Add un commentaire</legend>
<?php
    // Form
    echo $form->create('Comment', array('action' => 'add'));
    echo $form->hidden('model_type', array('value' => $model_type));
    echo $form->hidden('model_id', array('value' => $model_id));
    echo $form->input('content');
<?php
    echo $form->end('Send');
?>
</fieldset>
<div class="paginationBar">
    <?php
        echo $paginator->prev('<<  ', null, null, array('class' => 'disabled'));
        echo '<span class="pagination">',$paginator->numbers(),'</span>';
        echo $paginator->next('  >>', null, null, array('class' => 'disabled'));
    ?>
</div>
<?php
    foreach($comments as $comment){
        echo $this->element('comment', array('comment' => $comment));
    }
?>
<div class="paginationBar">
    <?php
        echo $paginator->prev('<<  ', null, null, array('class' => 'disabled'));
        echo '<span class="pagination">',$paginator->numbers(),'</span>';
        echo $paginator->next('  >>', null, null, array('class' => 'disabled'));
    ?>

    <p><br />
    <?php
        echo $paginator->counter(array('format' => 'Page %page% on %pages%, displayi  %current% items of %count%'));
    ?>
    </p>
</div>

评论元素

//{app}/views/elements/comment.ctp
// A single comment view
$id = $comment['Comment']['id'];
?>
<div class="comment">
<p class="com-author">
<span class="com-authorname"><?=$comment['User']['name']?>&nbsp;</span>
<span class="com-date">(<?=$comment['Comment']['created']?>)</span>
</p>
<p class="com-content"><?=$comment['Comment']['content']?></p>
</div>

答案 1 :(得分:1)

嗯......如果你想显示那样的分页评论会很复杂。你应该使用延迟加载:在用户点击之前不要加载评论。

你应该做一个元素。您可以将model_name和model_id传递给它。在元素中,您可以创建一个注释“小部件”,可以使用ajax直接将注释发送到您的注释控制器;并使用ajax加载分页注释。

答案 2 :(得分:1)

查看CakeDC开发的this插件(它实际上是一个组件)。

您可以实现该功能,也可以使用它来创建自己的解决方案。