Yii2. Запись данных в БД. Часть 2

31.03.2019

Теги: ActiveFormWeb-разработка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

Каталог оборудования
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Производители
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Функциональные группы
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.