СоХабр закрыт.
С 13.05.2019 изменения постов больше не отслеживаются, и новые посты не сохраняются.
Здравствуйте, уважаемые Хабровчане! Решил поделиться с вами довольно простым криворуким приёмом, как за 10 минут "поднять" чатик на "голом" yii2 с помощью pjax. Кому интересно про что речь, добро пожаловать под кат.
Думаю что большинство читателей, знакомых с yii2, также знакомы и с технологией pjax.
От БД нам нужна всего 1 таблица с сообщениями, создадим её в свойственной yii манере, с помощью миграции:
$ ./yii migrate/create init
use yii\db\Migration;
class m160923_115323_init extends Migration
{
public function up()
{
$this->createTable('message', [
'id' => $this->primaryKey(),
'from' => $this->integer()->notNull(),
'to' => $this->integer()->notNull(),
'text' => $this->text()->notNull()
]);
}
public function down()
{
$this->dropTable('message');
}
}
На данном этапе можно сразу описать модель сообщения с довольно важным методом, с помощью которого мы в дальнейшем будет получать экземпляр ActiveQuery для формирования самого чата:
namespace app\models;
use yii\db\ActiveQuery;
use yii\db\ActiveRecord;
/**
* @property int $id
* @property int $from
* @property int $to
* @property string $text
*/
class Message extends ActiveRecord
{
public function rules()
{
return [
[['from', 'to', 'text'], 'required'],
[['from', 'to'], 'integer'],
['text', 'string']
];
}
/**
* @param int $from
* @param int $to
* @return ActiveQuery
*/
public static function findMessages($from, $to)
{
return self::find()
->where(['from' => $from])
->orWhere(['from' => $to, 'to' => $from]);
}
}
вот собственно и всё, что нам потребуется от БД.
Контроллер у нас будет состоять всего из одного "экшна":
namespace app\controllers;
use app\models\Message;
use Yii;
use yii\filters\AccessControl;
use yii\helpers\VarDumper;
use yii\web\Controller;
class ChatController extends Controller
{
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'allow' => true,
'roles' => ['@'],
]
],
]
];
}
public function actionIndex($id)
{
$currentUserId = Yii::$app->user->identity->getId();
$messagesQuery = Message::findMessages($currentUserId, $id);
$message = new Message([
'from' => $currentUserId,
'to' => $id
]);
if ($message->load(Yii::$app->request->post()) && $message->validate()) {
$message->save();
$message = new Message([
'from' => $currentUserId
]);
if (Yii::$app->request->isPjax) {
return $this->renderAjax('_chat', compact('messagesQuery', 'message'));
}
}
if (Yii::$app->request->isPjax) {
return $this->renderAjax('_list', compact('messagesQuery', 'message'));
}
return $this->render('chat', compact('messagesQuery', 'message'));
}
}
Постараюсь пояснить, что происходит в "экшне":
А вот тут, по моему мнению, самое интересное. Для начала постараюсь пояснить логику обновления "чатика" при помощи pjax:
В нашем случае нам нужно:
<?php
/**
* @var \yii\web\View $this
* @var \app\models\Message $message
* @var \yii\db\ActiveQuery $messagesQuery
*/
?>
<?php \yii\widgets\Pjax::begin([
'timeout' => 3000,
'enablePushState' => false,
'linkSelector' => false,
'formSelector' => '.pjax-form'
]) ?>
<?= $this->render('_chat', compact('messagesQuery', 'message')) ?>
<?php \yii\widgets\Pjax::end() ?>
<?php $this->registerJs(<<<JS
function updateList() {
$.pjax.reload({container: '#list-messages'});
}
setInterval(updateList, 1000);
JS
) ?>
<?php
/**
* @var \yii\web\View $this
* @var \app\models\Message $message
* @var \yii\db\ActiveQuery $messagesQuery
*/
?>
<?php \yii\widgets\Pjax::begin([
'id' => 'list-messages',
'enablePushState' => false,
'formSelector' => false,
'linkSelector' => false
]) ?>
<?= $this->render('_list', compact('messagesQuery')) ?>
<?php \yii\widgets\Pjax::end() ?>
<?php \yii\widgets\ActiveForm::begin(['options' => ['class' => 'pjax-form']]) ?>
<?= \yii\bootstrap\Html::activeTextarea($message, 'text') ?>
<?= \yii\helpers\Html::submitButton('Отправить') ?>
<?php \yii\widgets\ActiveForm::end() ?>
<?php
/**
* @var \yii\web\View $this
* @var \yii\db\ActiveQuery $messagesQuery
*/
?>
<?= \yii\widgets\ListView::widget([
'itemView' => '_row',
'layout' => '{items}',
'dataProvider' => new \yii\data\ActiveDataProvider([
'query' => $messagesQuery,
'pagination' => false
])
]) ?>
<?php
/**
* @var \yii\web\View $this
* @var \app\models\Message $model
*/
?>
<div class="row">
<div class="col-md-3"><?= $model->from ?></div>
<div class="col-md-9"><?= $model->text ?></div>
</div>
комментарии (7)