S
S
Strodj2018-04-15 22:20:41
Yii
Strodj, 2018-04-15 22:20:41

How to organize different comments on each page, YII2?

controller

public function actionView($id){

...

         $model = new BlogForm();

        if ($model->load(Yii::$app->request->post()) && $model->post()) {
        return $this->refresh();
    }
       
        return $this->render('view', [
        'model' => $model,
    ]);
    }

model
class Blog extends ActiveRecord{

    public static function tableName(){
        return 'blog';
    }

        public function getCategory(){
        return $this->hasOne(Blog::className(), ['id' => 'id']);
    }

} 


class BlogForm extends Model
{
    public $nick ;
    public $email;
    public $body;

    /**
     * @return array the validation rules.
     */
    public function rules()
    {
        return [
            /* nick and comment body are both required */
            [[ 'body'], 'required'],
            [['email'], 'email'],
        ];
    }

    /**
     * Appends post to DB
     * @return boolean whether the post is appended successfully
     */
    public function post()
    {
        if ($this->validate()) {
            $db = Yii::$app->db;

            $nickSafe=Yii::$app->user->identity->email;
    

            $bodySafe = htmlspecialchars($this->body, ENT_QUOTES, "UTF-8");
            
            $db->createCommand('INSERT INTO comments (nick, body)' .
                ' VALUES (\'' . $nickSafe . '\',  REPLACE("' . $bodySafe . '", "\n", "<br />"));')->execute();
        
            return true;
        }
        return false;
    }
}

Performance
<div class="comments">
  <p >
      <?php Pjax::begin(); ?>
        <?php $form = ActiveForm::begin([
        'id' => 'post-comment-form',
        'options' => ['class' => 'form-horizontal'],
        'fieldConfig' => [
            'template' => "{label}\n<div class=\"col-lg-3\">{input}</div>\n<div class=\"col-lg-8\">{error}</div>",
            'labelOptions' => ['class' => 'col-lg-1 control-label'],
        ],
    ]); ?>

    <?php

    
    $field = $form->field($model, 'body', [
        'inputOptions' => [
            'placeholder' => $model->getAttributeLabel('body'),
        ],
    ])->label(false);
    $field->textArea([
        'rows' => '6'
    ]);
    echo $field;

    echo '<div class="form-group">';
    echo '<div class="col-lg-11">';
    echo Html::submitButton('Отправить', ['class' => 'btn btn-my']);
    echo '</div>';
    echo '</div>';
    
    ?>

    <?php ActiveForm::end(); ?>
     <?php Pjax::end(); ?>
    </p>

<div class="site-comments">
    <h3>Отзывы:</h3>

    <?php
    
    $db = Yii::$app->db;
    
    $comments = $db->createCommand('SELECT * FROM comments ORDER BY id DESC;')->queryAll();
    
    ?>

    <?php 
    $provider = new ArrayDataProvider([
        'allModels' => $comments,
        'pagination' => [
            'pageSize' => 10,
        ]
    ]);

        echo ListView::widget([
            'dataProvider' => $provider,
            'itemView' => function ($model, $key, $index, $widget) {
                if ($model['email']) {
                    return $this->renderDynamic('echo \'<b>' . $model['nick'] . '</b> (' . $model['email'] . '):<br>' . $model['body'] . '<br><br>\';');
                } else {
                    return $this->renderDynamic('echo \'<b>' . $model['nick'] . '</b>:<br>' . $model['body'] . '<br><br>\';');
                }
            },
            'emptyText' => 'Отзывов нет, будьте первым! '
        ])
    ?>
  </div>
</div>

Answer the question

In order to leave comments, you need to log in

[[+comments_count]] answer(s)
D
Dmitry Kim, 2018-04-16
@kimono

Don't do this, it can be dangerous:

$bodySafe = htmlspecialchars($this->body, ENT_QUOTES, "UTF-8");
            
            $db->createCommand('INSERT INTO comments (nick, body)' .
                ' VALUES (\'' . $nickSafe . '\',  REPLACE("' . $bodySafe . '", "\n", "<br />"));')->execute();
        
            return true;
        }
        return false;
    }

Do either this:
$comment = new Comment([
  'nick' => Yii::$app->user->identity->email,
  'body' => $this->body,
  'model' => 'news',
  'model_id' => 1234
]);
return $comment->save();

either like this:
$result = $db->createCommand('INSERT INTO comments (nick, body, model, model_id) VALUES (:nick, :body, :model, :model_id)', [
  'nick' => Yii::$app->user->identity->email,
  'body' => $this->body,
  'model' => 'news',
  'model_id' => 1234
])->execute();
return $result;

In view, output as Html::encode($body), why store HTML garbage in the database?

D
Dmitry, 2018-04-16
@slo_nik

Let's say there are two tables. The first stores articles, the second contains comments for each article.
The comments table has an id_article field that stores the article id.
You need to display a separate article and comments that belong to this article.
The link to view the article might look like this:
The controller has a view action to display a single article:

public function actionView($id)
{
    $comment = new Comments();
    $article = $this->findArticle($id);
    $query = Comments::find()->where('id_article=:id', [':id' => $id]);
    $dataProvider = new ActiveDataProvider([
        $query = $query
     ]);

     return $this->render('view', ['article' => $article, 'dataProvider' => $dataProvider, 'comment' => $comment])
}
public function findArticle($id)
{
   if(($model = Article::find()->where('id=:id', [':id' => $id])->one()) !== null){
        return $model;
   }
   else{
      throw new NotFoundHttpException();
   }
}

In view:
echo $article->title;
// вывод комментариев
        echo ListView::widget([
            'dataProvider' => $dataProvider,
           'itemView' => 'path_to_view'
        ])

In the comment submission form, a hidden field for the article id:
Something like that.
Everything!
ps I did not check for errors. I wrote everything in haste.
pss
An example of a comment model with a minimal set of fields. Namespace specify your
Comments
<?php

namespace app\modules\comments\models;

use Yii;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;

/**
 * This is the model class for table "{{%comments}}".
 *
 * @property int $id
 * @property string $body
 * @property int $id_article
 * @property int $created_at
 * @property int $update_at
 * @property int $status
 */
class Comments extends ActiveRecord
{
    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return '{{%comments}}';
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['body', 'status', 'id_article'], 'required'],
            [['id_article', 'created_at', 'update_at', 'status'], 'integer'],
            [['body'], 'string', 'max' => 300],
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'id' => Yii::t('app', 'ID'),
            'body' => Yii::t('app', 'Body'),
            'id_article' => Yii::t('app', 'Article ID'),
            'created_at' => Yii::t('app', 'Created At'),
            'update_at' => Yii::t('app', 'Update At'),
            'status' => Yii::t('app', 'Status'),
        ];
    }

    public function behaviors()
    {
        return TimestampBehavior::class;
    }
}

pss
Let's start over. Without foreach, pjax, in general, without any extra details.
Comments
<?php

namespace app\modules\comments\models; // укажите свой namespace

use Yii;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;

/**
 * This is the model class for table "{{%comments}}".
 *
 * @property int $id
 * @property string $body
 * @property int $id_article
 * @property int $created_at
 * @property int $update_at
 * @property int $status
 */
class Comments extends ActiveRecord
{
    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return '{{%comments}}';
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['body', 'status', 'id_article'], 'required'],
            [['id_article', 'created_at', 'update_at', 'status'], 'integer'],
            [['body'], 'string', 'max' => 300],
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'id' => Yii::t('app', 'ID'),
            'body' => Yii::t('app', 'Body'),
            'id_article' => Yii::t('app', 'Article ID'),
            'created_at' => Yii::t('app', 'Created At'),
            'update_at' => Yii::t('app', 'Update At'),
            'status' => Yii::t('app', 'Status'),
        ];
    }

    public function behaviors()
    {
        return TimestampBehavior::class;
    }
}

Action in controller
public function actionView($id)
{
    $comment = new Comments();
    
    $query = Comments::find()->where('id_article=:id', [':id' => $id]);

    $article = $this->findArticle($id);

    $dataProvider = new ActiveDataProvider([
        'query' => $query
    ]);  

    render $this->render('view', ['comment' => $comment, 'dataProvider' => $dataProvider, 'article' => $article);
}

public function findArticle($id)
{
   if(($model = Blog::find()->where('id=:id', [':id' => $id])->one()) !== null){
        return $model;
   }
   else{
      throw new NotFoundHttpException();
   }

}

In the view, we display the title of one news, comments on this news and a form for comments.
view.php
<?php
// через use подключаете необходимые классы, виджеты и тому подобное

// выводим заголовок новости.
echo $article->title;

// выводим комментарии
echo ListView::widget([
  'dataProvider' => $dataProvider
  'itemView' => '_view_comment' // содержимое файла будет ниже.
])

// выводим форму для комментариев
$form = ActiveForm::begin([
   'action' => 'путь_к_действию_создания_комментария'
])
echo $form->field($comment, 'body')->textInput(['placeholder' => 'Текст комментария')->label(false)
echo Html::submitButton('Отправить')
ActiveForm::end();
?>

The _view_comment.php file for the ListView(); widget. Put next to the view.php file
<div>
 <?= $model->body; ?>
</div>

By the way, your Blog model is suspicious. Have you shown the full code?
Everything.

S
Strodj, 2018-04-17
@Strodj

slo_nik , shared, and then decided to add what you wrote

$dataProvider = new ActiveDataProvider([
        $query = $query
     ]);

Error
Class 'app\controllers\ActiveDataProvider' not found
But I added use app\controllers\ActiveDataProvider;

M
Maxim Timofeev, 2018-04-18
@webinar

How to organize different comments on each page, YII2?

Output on each page is different. Probably store in the database the belonging of the comment to a particular page. For example, the model class and its id.
Why did you provide your code?
By the way, this is not allowed in the view:
Write a behavior that adds a connection to the model with comments and pull the connection.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question