В этой записи мы создадим форму, модель которая будет отвечать за проверку полей этой формы, воспользуемся миграцией и создадим новую таблицу с ее помощью, а так же научимся сохранять данные в базу в Yii2 basic.
Эта запись относится к курсу Yii2 basic.
Давайте создадим следующий функционал:
- Добавлять новые автомобили (поля: название, марку, описание, дата создания и обновления)
- Смотреть все добавленные автомобили с пагинацией (постраничный просмотр, например по 10 или 15 на страницу)
- Изменять машины
- Удалять машины
Создание ActiveRecord модели
Для начала, лучше всего создать модель, которая будет работать с базой данных.
Для этого нужно зайти в папку models
и создать новый PHP файл. Назовем его Car
:
<?php namespace app\models; use yii\db\ActiveRecord; class Car extends ActiveRecord { public static function tableName() { return 'cars'; } }
Как видим класс Car
заимствует все методы из класса ActiveRecord
. ActiveRecord
— помогает работать с базой данных, а конкретнее с таблицей cars
, которая указана в статическом методе tableName()
.
Сейчас этот класс бесполезен, потому что таблицу cars
еще предстоит создать.
Сделать это можно двумя способами:
- Через phpMyAdmin
- Через миграции (лучший вариант)
Почему миграции лучше, я уже ранее описывал в этом курсе, если вы внимательно его читали. Ниже как раз секция о том, как это сделать с помощью миграций.
Создание новой таблицы, используем миграции
Давайте для начала создадим миграцию новой таблицы и назовем её — cars
.
Зайдите в корневую папку проекта:
$ cd /var/www/yii-dev/
И напишите следующее:
$ php yii migrate/create create_cars_table
Где «create_cars_table» — это название миграции.
С помощью команды migrate/create
вы указываете yii, что хотите создать новую миграцию.
Полный список доступных команды вы можете посмотреть написав
$ php yii
и нажав «Enter».
В ответ у вас выведется следующее:
Yii Migration Tool (based on Yii v2.0.12) Create new migration '/var/www/yii-dev/migrations/m170825_174453_create_cars_table.php'? (yes|no) [no]:
Вам нужно ввести «yes» и нажать «Enter».
После чего у вас должна создаться папка migrations
, в которой появится новый файл с названием похожий на этот — m170825_174453_create_cars_table.php
. Я написал «похожий», потому что часть «m170825_174453» будет различаться в зависимости от времени когда создавалась миграция.
«m170825_174453» можно расшифровать следующим образом — «m<ГГММДД_ЧЧММСС>_<Название>».
Файл m170825_174453_create_cars_table
должен выглядеть следующее образом:
<?php use yii\db\Migration; /** * Handles the creation of table `cars`. */ class m170825_174453_create_cars_table extends Migration { /** * @inheritdoc */ public function up() { $this->createTable('cars', [ 'id' => $this->primaryKey(), ]); } /** * @inheritdoc */ public function down() { $this->dropTable('cars'); } }
Метод up()
используется для того, чтобы что-то изменять в базе вперед. То есть вы добавите новую таблицу, колонку, измените тип колонки и др.
Метод down()
возвращает изменения, которые были сделаны в up()
. То есть down()
— это up()
в обратную сторону.
Эти два метода нужны для того, чтобы мы могли спокойно создать новую миграцию и если вас что-то не устроит в ней, использовать метод down()
и вернуться обратно.
Yii2 знает о стандартный вариантам создания миграций, поэтому когда вы пишите «created_{название_таблицы}_table», то он понимает, что вы хотите создать новую таблицу и заранее подготавливает файл для этого, собственно как вы и можете видеть выше.
Но это не значит, что вся работа будет сделано за нас. Теперь нам нужно дописать дополнительные колонки для таблицы.
В конечном итоге из миграции выше, нам нужно изменить только метод up()
, который отвечает за создание:
... /** * @inheritdoc */ public function up() { $this->createTable('cars', [ 'id' => $this->primaryKey(), 'name' => $this->string(255)->notNull(), 'model' => $this->string(255)->notNull(), 'description' => $this->string(500)->null(), 'created_at' => $this->integer()->notNull(), 'updated_at' => $this->integer()->notNull() ]); } ...
$this->string()
означает, что поле будет строкой$this->primaryKey()
— что поле будет уникальным ключом числового типа$this->integer()
сделает поле числовым
Как параметр вы можете указать длину для
$this->string()
или$this->integer()
, а так же многих других методов помощников. В примере выше это 255 и 500. Так же, можно указатьnull()
илиnotNull()
— это разрешить полю быть NULL или нет.
Теперь если вы введете в корне проекта:
$ php yii migrate/up
Вы увидите следующее сообщение:
Yii Migration Tool (based on Yii v2.0.12) Total 1 new migration to be applied: m170825_174453_create_cars_table Apply the above migration? (yes|no) [no]:
Сообщение «Total 1 new migration to be applied:» означает, что у вас есть новые миграции, которые еще не были активированы и ниже список названий. Чтобы их запустить, вам нужно ввести «yes» и нажать «Enter».
Если все окей, у вас покажет следующее сообщение:
*** applying m170825_174453_create_cars_table > create table cars ... done (time: 0.027s) *** applied m170825_174453_create_cars_table (time: 0.079s) 1 migration was applied. Migrated up successfully.
Большая его часть будет зеленым.
Теперь вы можете зайти в phpMyAdmin, в базу yii_loc
и проверить наличие таблицы cars
, выглядит это все примерно следующим образом:
Создание контроллера, экшена и использование модели
Создадим новый контроллер в папку controllers и назовем его CarController:
<?php namespace app\controllers; use yii\web\Controller; class CarController extends Controller { }
Теперь создадим action create
, который будет отвечать за добавление новой машины.
<?php namespace app\controllers; use yii\web\Controller; class CarController extends Controller { public function actionCreate() { ... } }
Теперь добавим все элементы этого action, новые строки выделы ниже:
<?php namespace app\controllers; use Yii; use app\models\Car; use yii\web\Controller; class CarController extends Controller { public function actionCreate() { $model = new Car(); if( $model->load(Yii::$app->request->post()) && $model->validate() ) { if( $model->save() ) { return $this->refresh(); } } return $this->render('create', ['model' => $model]); } }
Внутри, нам нужно использовать модель Cars
, которая будет проверять форму и возвращать ответ в шаблон create.php
, который находиться в views/car/
.
Для правильного отображения шаблонов контроллера, во views
нужно создать папку car
, и внутри создать файл create.php
.
Чтобы не париться по поводу создания create.php
, скопируйте все из views/site/login.php
и подправьте код под. У вас должно получиться что-то похожее на это:
<?php /* @var $this yii\web\View */ /* @var $form yii\bootstrap\ActiveForm */ /* @var $model app\models\Car */ use yii\helpers\Html; use yii\bootstrap\ActiveForm; $this->title = 'Добавить новую машину'; $this->params['breadcrumbs'][] = $this->title; ?> <div class="site-login"> <h1><?= Html::encode($this->title) ?></h1> <?php $form = ActiveForm::begin([ 'id' => 'add-new-car', 'layout' => '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'], ], ]); ?> <?= $form->field($model, 'name')->textInput() ?> <?= $form->field($model, 'model')->textInput() ?> <?= $form->field($model, 'description')->textarea() ?> <div class="form-group"> <div class="col-lg-offset-1 col-lg-11"> <?= Html::submitButton('Добавить', ['class' => 'btn btn-primary', 'name' => 'add-new-car--button']) ?> </div> </div> <?php ActiveForm::end(); ?> </div>
Для создания формы лучше всегда использовать класс ActiveForm
, потому что он заботится о безопасности, создавая скрытое поле с CSRF токеном и другие удобности в виде авто генерации полей формы, валидация и другой. У ActiveForm
есть открывающийся формат и закрывающийся. Между ними пишутся элементы формы для ввода информации и, конечно же, кнопка отправки формы.
Обратите внимание на $this->title
— этот атрибут задает название страницы в <head></head>
.
Так же посмотрите на:
$this->params['breadcrumbs'][] = $this->title
Эта строка создает хлебные крошки, которые появятся автоматически над вашим шаблоном. А как название для хлебной крошки, мы так же используем $this->title
, которые уже указали выше.
Открывающийся формат:
<?php $form = ActiveForm::begin([ ... ]); ?>
Закрывающийся:
<?php ActiveForm::end(); ?>
Пример элемента формы:
<?= $form->field($model, 'name')->textInput() ?>
Этот элемент означает, что вы хотите создать обычный текстовый элемент формы, который равен следующему HTML:
<input type="text" id="cars-name" class="form-control" name="Car[name]">
Метод textarea()
равен <textarea></textarea>
элементу соответственно.
Обратите внимание, что название полей в форме точно такие же как названия колонок в таблице
cars
в базе данных. Это не случайно — они должны совпадать.
Вы уже можете зайти на car/create
и посмотреть на форму, которую вы только что сами создали. Пока что она работает только на половину, не добавляя в базу именно те данные, которые вы напишите. Все поля будут пустыми.
Для того, чтобы все было как надо, вам нужно добавить правила проверки полей в класс Car
.
Заходим в models/Car.php
и меняем его следующим образом:
<?php namespace app\models; use yii\db\ActiveRecord; use yii\behaviors\TimestampBehavior; /** * Class Car * * @property string name Имя машины. * @property string model Название модели машины. * @property string description Описание машины. * @property integer updated_at Когда машина была обновлена. * @property integer created_at Когда машина была создана. * * @package app\models */ class Car extends ActiveRecord { public static function tableName() { return 'cars'; } public function rules() { return [ [['name', 'model'], 'required'], [['name', 'model', 'description'], 'trim'], [['name', 'model'], 'string', 'max' => 255], ['description', 'string', 'max' => 500], ]; } public function behaviors() { return [ TimestampBehavior::className(), ]; } }
Добавились два новых метода: rules()
и behaviors()
. Оба метода перезаписываются из ActiveRecord
.
rules()
— это правила проверки полей формы. Самое первое правило — указывает на то, что поляname
иmodel
являются обязательными для заполнения, второе — что мы чистим поляname
,model
иdescription
от лишних пробелов с помощьюtrim
, третье — длинна строки для полейname
иmodel
не должно превышать 255 символов используя'string', 'max' => 255
, ну и четвертое правило — это почти повтор третьего, только длинна строки больше и все.behaviors()
— это поведение моделиCar
. Внутри может быть множество сценариев, но у нас будет только один — этоTimestampBehavior
. Этот класс отвечает за добавление дат при добавлении или обновлении информации (в данном случае о машине). То есть когда мы добавим новую машину,TimestampBehavior
автоматически заполнитcreated_at
иupdated_at
с нужной датой. При обновлении машины, он только обновимupdated_at
— как и должно быть.
Читать далее — Yii2 basic: Просмотр, изменение и удаление автомобилей