03Первое приложение
Четыре шага из руководства «Первое знакомство» в одном месте: страница «Привет», форма с валидацией, список из базы данных и генерация CRUD в Gii.
Здесь весь путь новичка: действие и представление → модель и форма → Active Record с пагинацией → CRUD за минуту в Gii. Каждый шаг показывает одну часть MVC и знакомит с идеями, которые дальше разбираются подробно.
Шаг 1. Страница «Привет»: действие + представление#
Действие — публичный метод контроллера с префиксом action. Параметры действия берутся из $_GET по имени.
namespace app\controllers;
use yii\web\Controller;
class SiteController extends Controller
{
public function actionSay($message = 'Привет')
{
return $this->render('say', ['message' => $message]);
}
}<?php use yii\helpers\Html; ?>
<?= Html::encode($message) ?>Открываем index.php?r=site/say&message=Привет+мир. Параметр r — это маршрут вида контроллер/действие; site/say → SiteController::actionSay().
Правила именования, которые нужно запомнить:
| Идентификатор | Класс / метод |
|---|---|
контроллер site | app\controllers\SiteController |
контроллер post-comment | app\controllers\PostCommentController |
действие say | actionSay() |
действие create-comment | actionCreateComment() |
представление say контроллера site | views/site/say.php |
render() автоматически оборачивает результат в шаблон views/layouts/main.php — поэтому у новой страницы сразу есть шапка и подвал сайта.
Шаг 2. Форма: модель + валидация#
Модель формы наследует yii\base\Model: публичные свойства — это атрибуты, метод rules() — правила проверки.
namespace app\models;
use yii\base\Model;
class EntryForm extends Model
{
public $name;
public $email;
public function rules()
{
return [
[['name', 'email'], 'required'],
['email', 'email'],
];
}
}public function actionEntry()
{
$model = new EntryForm();
// load() кладёт $_POST['EntryForm'] в атрибуты, validate() проверяет по rules()
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
return $this->render('entry-confirm', ['model' => $model]);
}
return $this->render('entry', ['model' => $model]); // первый показ или ошибки
}<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
?>
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'name')->label('Ваше имя') ?>
<?= $form->field($model, 'email') ?>
<div class="form-group">
<?= Html::submitButton('Отправить', ['class' => 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>Yii::$app — глобальный объект приложения и одновременно Service Locator: через него доступны компоненты request, response, db, user и другие.
Шаг 3. Данные из базы: Active Record + пагинация#
Подключение описано в config/db.php и доступно как Yii::$app->db:
return [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=yii2basic',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
];Класс Active Record без единой строки кода уже умеет всё — имя таблицы выводится из имени класса (Country → country):
namespace app\models;
use yii\db\ActiveRecord;
class Country extends ActiveRecord
{
}$countries = Country::find()->orderBy('name')->all(); // все строки как объекты
$country = Country::findOne('US'); // по первичному ключу
$country->name = 'U.S.A.';
$country->save(); // UPDATEКонтроллер со списком и постраничной разбивкой:
namespace app\controllers;
use yii\web\Controller;
use yii\data\Pagination;
use app\models\Country;
class CountryController extends Controller
{
public function actionIndex()
{
$query = Country::find();
$pagination = new Pagination([
'defaultPageSize' => 5,
'totalCount' => $query->count(),
]);
$countries = $query->orderBy('name')
->offset($pagination->offset)
->limit($pagination->limit)
->all();
return $this->render('index', [
'countries' => $countries,
'pagination' => $pagination,
]);
}
}<?php
use yii\helpers\Html;
use yii\widgets\LinkPager;
?>
<h1>Countries</h1>
<ul>
<?php foreach ($countries as $country): ?>
<li><?= Html::encode("{$country->code} ({$country->name})") ?>: <?= $country->population ?></li>
<?php endforeach; ?>
</ul>
<?= LinkPager::widget(['pagination' => $pagination]) ?>Pagination считает LIMIT/OFFSET по параметру page из URL, а LinkPager рисует кнопки страниц. Всё это подробно — в разделах Active Record и Провайдеры данных.
Шаг 4. Gii: генерация модели и CRUD#
Gii — модуль, включённый в config/web.php только для YII_ENV_DEV:
if (YII_ENV_DEV) {
$config['bootstrap'][] = 'gii';
$config['modules']['gii'] = [
'class' => 'yii\gii\Module',
'allowedIPs' => ['127.0.0.1', '::1', '192.168.0.*'], // по умолчанию только localhost
];
}Открываем index.php?r=gii и:
- Model Generator: таблица
country→ классCountry. Кнопка Preview покажет файл, diff — отличия от существующего, флажок overwrite перезапишет. - CRUD Generator:
app\models\Country, поисковая модельapp\models\CountrySearch, контроллерapp\controllers\CountryController. - Получаем
controllers/CountryController.php,models/CountrySearch.phpиviews/country/*.php— таблицу с сортировкой и фильтрами, просмотр, создание, редактирование, удаление.
app\controllers\PostCommentController::actionCreateReply() — дефисы убираются, слова капитализируются, добавляются суффикс Controller и префикс action.
Копирует $_POST['EntryForm'] в безопасные атрибуты модели и возвращает true; если данных нет — false, и действие просто показывает форму.
И на клиенте (JavaScript, сгенерированный из rules()), и на сервере при вызове validate(). Доверять можно только серверной.
Только настроенное подключение db и таблица country в базе: имя таблицы, атрибуты и типы столбцов читаются из схемы автоматически.
Из соображений безопасности: генератор пишет файлы на диск. Разрешённые адреса задаются в allowedIPs.