Cakephp: мультимодельная система комментариев - PullRequest
2 голосов
/ 27 июля 2011

Я использую cakephp, у меня есть модель "comment" с двумя полями: "model_type" и "model_id", чтобы комментировать каждый элемент моего приложения (например, Picture, News, Article, ...) один комментарий модель.

Интересно, как это сделать. (Компонент «Комментарий» для контроллера, который можно прокомментировать?)

Наконец, я хочу отобразить комментарий с помощью помощника: $ comment-> show ('model_name', 'item_id'); это будет отображать правильно разбитые на страницы комментарии и форму для добавления нового комментария к элементу.

Спасибо.

Ответы [ 3 ]

5 голосов
/ 27 июля 2011

Редактировать: См. Также: 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 голос
/ 27 июля 2011

Проверьте этот плагин (на самом деле это компонент), разработанный CakeDC.

Вы можете либо реализовать это, либо использовать его для создания собственного решения.

1 голос
/ 27 июля 2011

хм ... было бы довольно сложно, если вы хотите отображать постраничные комментарии, как это.Вы должны использовать отложенную загрузку: на самом деле не загружайте комментарии, пока пользователь не нажмет на них или что-то в этом роде.

Вы, вероятно, должны создать элемент.Вы можете передать имя_модели и имя_модели к нему.А в элементе вы можете создать «виджет» комментария, который может напрямую отправлять комментарий вашему контроллеру комментариев, используя ajax;и загрузите постраничные комментарии, используя ajax.

...