Yii2. Запись данных в БД. Часть 2
31.03.2019
Теги: ActiveForm • Web-разработка • Yii2 • БазаДанных • Запрос • Теория • Удалить • Фреймворк
Метод save()
может вставить или обновить строку данных в зависимости от состояния ActiveRecord объекта. Если объект создан с помощью оператора new
, вызов метода save()
приведёт к вставке новой строки данных. Если же объект был получен с помощью запроса на получение данных, вызов save()
обновит строку таблицы, соответствующую объекту ActiveRecord.
Различать два состояния ActiveRecord объекта можно с помощью проверки значения его свойства isNewRecord
. Это свойство также используется внутри метода save()
:
public function save($runValidation = true, $attributeNames = null) { if ($this->getIsNewRecord()) { return $this->insert($runValidation, $attributeNames); } else { return $this->update($runValidation, $attributeNames) !== false; } }
insert()
или update()
непосредственно, чтобы вставить или обновить строку данных в таблице.
Т.к. класс yii\db\ActiveRecord
наследует класс yii\base\Model
, он обладает такими же возможностями валидации данных. Можно объявить правила валидации, переопределив метод rules()
и осуществлять валидацию данных посредством вызовов метода validate()
.
При вызове метода save()
, по умолчанию он автоматически вызывает метод validate()
. Только после успешного прохождения валидации происходит сохранение данных; в ином случае метод save()
просто возвращает false
, и для получения сообщения об ошибках можно проверить свойство errors
.
Давайте посмотрим, как можно использовать методы insert()
, update()
и delete()
. У нас уже есть форма обратной связи и мы умеем сохранять сообщения в базу данных. Добавим возможность просмотра списка всех сообщений и возможность их редактирования и удаления.
Модель остается без изменений:
<?php namespace app\models; use yii\db\ActiveRecord; /** * Модель для формы обратной связи */ class Feedback extends ActiveRecord { public function attributeLabels() { return [ 'name' => 'Ваше имя', 'email' => 'Ваш email', 'body' => 'Сообщение', ]; } public function rules() { return [ // удалить пробелы для полей name и email [['name', 'email'], 'trim'], // поле name обязательно для заполнения ['name', 'required', 'message' => 'Поле «Ваше имя» обязательно для заполнения'], // поле email обязательно для заполнения ['email', 'required', 'message' => 'Поле «Ваш email» обязательно для заполнения'], // поле email должно быть корректным адресом почты ['email', 'email', 'message' => 'Поле «Ваш email» должно быть адресом почты'], // поле body обязательно для заполнения ['body', 'required', 'message' => 'Поле «Сообщение» обязательно для заполнения'], ]; } }
Контроллер содержит action
-ы:
actionIndex()
— список всех сообщенийactionInsert()
— добавляет новое сообщениеactionUpdate()
— позволяет обновить сообщениеactionDelete()
— позволяет удалить сообщение
<?php namespace app\controllers; use Yii; use yii\web\Controller; use app\models\Feedback; class PageController extends Controller { /* * Список всех сообщений */ public function actionIndex() { $messages = Feedback::find()->asArray()->all(); return $this->render('index', ['messages' => $messages]); } /* * Добавляет новое сообщение */ public function actionInsert() { $message = new Feedback(); // если пришли post-данные if ($message->load(Yii::$app->request->post())) { // проверяем и сохраняем эти данные if ($message->insert()) { // данные прошли валидацию и записаны в БД return $this->redirect(['page/index']); } // данные не прошли валидацию Yii::$app->session->setFlash( 'success', false ); } return $this->render('feedback', ['message' => $message]); } /* * Позволяет обновить сообщение */ public function actionUpdate($id) { if (!ctype_digit($id)) { return $this->redirect(['page/index']); } $message = Feedback::findOne($id); // если пришли post-данные if ($message->load(Yii::$app->request->post())) { // проверяем и сохраняем эти данные if ($message->update()) { // данные прошли валидацию и записаны в БД return $this->redirect(['page/index']); } // данные не прошли валидацию Yii::$app->session->setFlash( 'success', false ); } return $this->render('feedback', ['message' => $message]); } /* * Позволяет удалить сообщение */ public function actionDelete($id) { if (!ctype_digit($id)) { return $this->redirect(['page/index']); } $message = Feedback::findOne($id); $message->delete(); return $this->redirect(['page/index']); } }
И два view-шаблона — для списка сообщений и для формы добавления и редактирования:
<?php /* @var $this yii\web\View */ use yii\helpers\Html; use yii\helpers\Url; $this->title = 'Все сообщения'; ?> <div class="page-index"> <h1><?= Html::encode($this->title) ?></h1> <p><a href="<?= Url::toRoute(['page/insert']); ?>">Добавить сообщение</a></p> <?php if (!empty($messages)): ?> <table class="table table-bordered"> <thead> <tr> <th>Id</th> <th>Имя</th> <th>E-mail</th> <th>Сообщение</th> <th>Редактировать</th> <th>Удалить</th> </tr> </thead> <tbody> <?php foreach($messages as $message): ?> <tr> <td><?= $message['id'] ?></td> <td><?= $message['name'] ?></td> <td><?= $message['email'] ?></td> <td><?= $message['body'] ?></td> <?php $url = Url::toRoute(['page/update', 'id' => $message['id']]); ?> <td><a href="<?= $url; ?>">Редактировать</a></td> <?php $url = Url::toRoute(['page/delete', 'id' => $message['id']]); ?> <td><a href="<?= $url; ?>">Удалить</a></td> </tr> <?php endforeach; ?> </tbody> </table> <?php endif; ?> </div>
<?php /* @var $this yii\web\View */ use yii\widgets\ActiveForm; use yii\helpers\Html; $this->title = 'Редактировать сообщение'; ?> <?php if (Yii::$app->session->hasFlash('success')): ?> <?php Yii::$app->session->getFlash('success'); /* очищаем данные сессии */ ?> <p>Данные формы не прошли валидацию</p> <?php endif; ?> <div class="page-feedback"> <h1><?= Html::encode($this->title) ?></h1> <?php $form = ActiveForm::begin(['id' => 'feedback-form', 'options' => ['novalidate' => '']]); ?> <?= $form->field($message, 'name')->textInput(); ?> <?= $form->field($message, 'email')->textInput(); ?> <?= $form->field($message, 'body')->textarea(['rows' => 5]); ?> <?= Html::submitButton('Сохранить', ['class' => 'btn btn-primary']); ?> <?php ActiveForm::end(); ?> </div>
Часто бывает необходимым обновить или удалить несколько записей по одному условию. Для этого есть методы updateAll()
и deleteAll()
.
Feedback::updateAll(['name' => 'Сергей Иванов'], ['email' => 'ivanov.s@mail.ru']);
UPDATE `feedback` SET `name` = 'Сергей Иванов' WHERE `email` = 'ivanov.s@mail.ru'
Feedback::deleteAll(['<', 'id', 5]);
DELETE FROM `feedback` WHERE `id` < 5
Дополнительно
Поиск: Yii2 • База данных • Удалить • Фреймворк • save • INSERT • UPDATE • DELETE • ActiveRecord • Web-разработка • Запрос • ActiveForm