Модели и ActiveRecord в Yii 2: пошаговая инструкция
Свяжете таблицу базы с классом на PHP, научитесь читать, создавать, обновлять и удалять записи без единого SQL-запроса. Займёт около 40 минут, если Yii уже установлен.

К концу этой инструкции у вас будет класс, который читает и пишет данные в таблицу MySQL без единой строки SQL: вызовы вида User::findOne(1) и $user->save(). Это база работы с данными в Yii 2 — фреймворк по-прежнему живёт в ветке 2.0.x, и приёмы ниже проверены на 2.0.49. Отдельная тема — валидация и связи между таблицами; здесь разбираем только базовый CRUD одной модели.
Что нужно иметь до начала
Проверьте это до первой команды, иначе застрянете на середине.
- PHP 7.4 или новее (Yii 2.0.49 работает и на PHP 8.1);
- установленный проект на Yii 2 — например, шаблон yii2-app-basic через Composer;
- работающая база данных: MySQL, MariaDB или PostgreSQL;
- доступ к консоли, где выполняется команда
./yiiиз корня проекта; - таблица в базе, к которой будем привязывать модель. Если её нет — создадим ниже.
Что такое ActiveRecord одним абзацем
ActiveRecord* — это подход, при котором одна строка таблицы соответствует одному объекту PHP, а столбцы становятся свойствами объекта. Вы работаете с $user->email, а фреймворк сам превращает это в SELECT, INSERT или UPDATE.
* ActiveRecord — паттерн доступа к данным, описанный Мартином Фаулером. В Yii его реализует базовый класс yii\db\ActiveRecord.
Шаг 1. Настройте подключение к базе
Откройте файл config/db.php. В шаблоне basic он выглядит примерно так — впишите свои параметры:
<?php
return [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=shop',
'username' => 'shop_user',
'password' => 'YOUR_DB_PASSWORD',
'charset' => 'utf8mb4',
];
Проверка: выполните в консоли ./yii. Если список команд вывелся без исключения о подключении к базе, конфиг прочитан. Ошибку соединения фреймворк покажет позже, при первом запросе.
Шаг 2. Создайте таблицу через миграцию
Если таблицы ещё нет, создайте её миграцией — так схема останется в репозитории. Сгенерируйте файл:
./yii migrate/create create_user_table
Откройте созданный файл в migrations/ и опишите структуру в методе safeUp():
public function safeUp()
{
$this->createTable('{{%user}}', [
'id' => $this->primaryKey(),
'email' => $this->string(255)->notNull()->unique(),
'name' => $this->string(120)->notNull(),
'created_at' => $this->integer(),
]);
}
public function safeDown()
{
$this->dropTable('{{%user}}');
}
Примените миграцию:
./yii migrate
Проверка: в консоли появится строка вида *** applied m2401..._create_user_table (time: ...), а в базе — таблица user.
Шаг 3. Создайте класс модели
Модель проще не писать руками, а сгенерировать инструментом Gii. Но для понимания сделаем минимальный класс вручную в models/User.php:
<?php
namespace app\models;
use yii\db\ActiveRecord;
class User extends ActiveRecord
{
// Явно указываем имя таблицы.
// Без этого метода Yii выведет имя из класса: user.
public static function tableName()
{
return '{{%user}}';
}
}
Конструкция {{%user}} — это имя таблицы с учётом префикса, заданного в конфиге. Если префикса нет, подставится просто user.
Проверка: откройте консоль Yii через ./yii и убедитесь, что при обращении к app\models\User в коде ошибки «class not found» не возникает. Проще всего проверить на следующем шаге запросом.
Быстрее — через Gii
Если проект в режиме разработки, зайдите в браузере на /index.php?r=gii, выберите Model Generator, укажите таблицу user и нажмите Generate. Gii сам заполнит правила валидации и подписи атрибутов. Ручной способ выше нужен, чтобы понимать, что именно генерируется.
Шаг 4. Прочитайте данные
Добавьте в таблицу одну строку любым способом (через phpMyAdmin или SQL), затем попробуйте достать её. Удобнее всего проверять в контроллере — создайте временный экшен или используйте существующий:
use app\models\User;
// По первичному ключу
$user = User::findOne(1);
// По условию — вернёт первую подходящую запись или null
$byEmail = User::findOne(['email' => 'ivan@example.com']);
// Все записи, отсортированные по имени
$all = User::find()
->orderBy('name')
->all();
// Количество без выборки строк
$count = User::find()->count();
Разница важная: findOne() сразу возвращает объект модели или null, а find() отдаёт объект запроса ActiveQuery, который надо завершить методом all(), one(), count() или похожим.
Проверка: выведите $user->email. Если увидели адрес из базы — чтение работает.
Шаг 5. Создайте и обновите запись
Новая запись — это новый объект. Заполните свойства и вызовите save():
$user = new User();
$user->email = 'anna@example.com';
$user->name = 'Анна';
$user->created_at = time();
if ($user->save()) {
// Yii сам подставит сгенерированный id
echo 'Создан пользователь #' . $user->id;
} else {
// Ошибки валидации, если правила заданы
var_dump($user->getErrors());
}
Обновление отличается только тем, что объект вы не создаёте, а находите:
$user = User::findOne(1);
$user->name = 'Анна Петрова';
$user->save();
Метод save() сам решает, делать INSERT или UPDATE: у найденного объекта свойство isNewRecord равно false, у нового — true.
Проверка: при создании save() вернёт true и заполнит $user->id. Если вернулся false — смотрите getErrors(), скорее всего сработало правило валидации или уникальность email.
Еслиsave()молча возвращаетfalse, аgetErrors()пуст — почти всегда виноваты правила валидации в методеrules(): атрибут, который вы заполняете, не прошёл проверку или не помечен как безопасный для присвоения.
Шаг 6. Удалите запись
$user = User::findOne(1);
if ($user !== null) {
$user->delete();
}
Чтобы удалить сразу несколько строк без загрузки объектов, используйте статический метод — он выполнит один DELETE:
// Удалит всех без имени
User::deleteAll(['name' => '']);
Проверка: delete() возвращает число удалённых строк. Ноль означает, что запись уже отсутствовала.
Полная шпаргалка методов
| Задача | Вызов | Что вернёт |
|---|---|---|
| Найти по ключу | User::findOne(1) | Объект или null |
| Найти по условию | User::findOne(['email' => $e]) | Объект или null |
| Все записи | User::find()->all() | Массив объектов |
| Первая по условию | User::find()->where([...])->one() | Объект или null |
| Количество | User::find()->count() | Число |
| Сохранить | $user->save() | true / false |
| Удалить объект | $user->delete() | Число строк |
| Удалить пачкой | User::deleteAll([...]) | Число строк |
Если не получилось
- «SQLSTATE[HY000] [1045] Access denied for user» — неверные логин или пароль в
config/db.php. Проверьте, что пользователь базы существует и имеет права на схему. - «Table 'shop.user' doesn't exist» — миграция не применена или имя таблицы в
tableName()не совпадает с реальным. Запустите./yii migrateи сверьте имя. - «Class 'app\models\User' not found» — не совпадает namespace с путём файла или имя класса с именем файла. В шаблоне basic файл
models/User.phpдолжен объявлятьnamespace app\models;. save()вернул false, ошибок нет — атрибуты не помечены как безопасные. Либо задайтеrules(), либо присваивайте свойства напрямую (как в примерах выше), а не через$user->attributes = $post.- Пустой результат
find()->all()— вы забыли вызватьall()и работаете с объектомActiveQuery, а не с массивом. Без завершающего метода запрос к базе не уходит.
Что делать дальше
CRUD одной таблицы — только вход. Следующие шаги в порядке пользы:
- заполните метод
rules()для валидации перед сохранением иattributeLabels()для подписей в формах; - изучите связи
hasOne()иhasMany()— они заменяют ручныеJOIN; - для списков с постраничкой посмотрите
ActiveDataProviderиGridView; - под нагрузкой следите за проблемой N+1 запросов:
with()подгружает связи одним запросом вместо десятков. Это отдельная тема — здесь мы её только называем.
Точные сигнатуры методов и список доступных операций проверяйте в официальном руководстве Yii 2 к вашей версии — API между минорными релизами 2.0.x стабилен, но детали лучше сверять.
Репетитор 1—11 класс и ВУЗ: Математика и физика методом наведения на мысль, помощь с ДЗ.
Спросить за 8 ₽Источники: Yii 2.0 Guide — Active Record, Yii 2.0 Guide — Database Migrations
Частые вопросы
У меня Yii 3, эти примеры подойдут?
Обязательно ли создавать таблицу через миграцию?
Чем findOne отличается от find()->one()?
Почему save() возвращает false, хотя данные корректные?
Как выполнить сырой SQL, если ActiveRecord не хватает?
Нужно ли генерировать модель через Gii или можно писать руками?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.