Если вы спрашиваете: «Что такое Yii?» Посмотрите мой предыдущий учебник: Введение в Yii Framework , который рассматривает преимущества Yii и содержит обзор изменений в Yii 2.0, выпущенном в октябре 2014 года.
В этой серии «Программирование с Yii2» я расскажу читателям, как использовать Yii2 Framework для PHP. В сегодняшнем уроке я расскажу вам об использовании объектно-реляционного отображения Yii, известного как ORM, для работы с базами данных. Он называется Active Record и является ключевым аспектом эффективного программирования приложений баз данных в Yii.
Yii предлагает различные способы программной работы с вашей базой данных, такие как прямые запросы и построитель запросов , но использование Active Record предлагает полный набор преимуществ для объектно-ориентированного программирования баз данных. Ваша работа становится более эффективной, более безопасной, работает в архитектуре контроллера представления модели Yii и переносима, если вы решите переключить платформы баз данных (например, MySQL на PostgreSQL).
Следуйте, как я подробно излагаю основы Active Record в Yii.
Просто напоминание, я участвую в комментариях ниже. Мне особенно интересно, если у вас есть другие подходы, дополнительные идеи или вы хотите предложить темы для будущих уроков. Если у вас есть вопрос или предложение по теме, пожалуйста, напишите ниже. Вы также можете связаться со мной через Twitter @reifman напрямую.
Что такое активная запись?
Контроллер представления модели Yii — одно из его ключевых преимуществ. Active Record предоставляет объектно-ориентированное решение для работы с базами данных, которое тесно интегрировано с моделями Yii. Согласно Wikipedia , общий термин Active Record был назван Мартином Фаулером в его книге 2003 года « Шаблоны архитектуры корпоративных приложений ».
В документации по Yii это краткое изложение:
Класс Active Record связан с таблицей базы данных, экземпляр Active Record соответствует строке этой таблицы, а атрибут экземпляра Active Record представляет значение определенного столбца в этой строке. Вместо написания необработанных операторов SQL вы должны обращаться к атрибутам Active Record и вызывать методы Active Record для доступа к данным, хранящимся в таблицах базы данных, и манипулирования ими.
Интеграция паттернов Active Record в Yii является сильной стороной фреймворка, но она характерна для большинства фреймворков, таких как Ruby on Rails.
Эта абстракция от моделей до таблиц базы данных позволяет каркасу повсеместно выполнять тяжелую работу по обеспечению безопасности, например разбивать запросы на внедрение SQL .
Поддержка Active Record в Yii также обеспечивает переносимость между несколькими базами данных. Вы можете переключать базы данных без необходимости менять много кода:
- MySQL 4.1 или более поздняя версия
- PostgreSQL 7.3 или более поздняя версия
- SQLite 2 и 3
- Microsoft SQL Server 2008 или более поздняя версия
- CUBRID 9,3 или позже
- оракул
- Сфинкс: через yii \ sphinx \ ActiveRecord , требуется расширение
yii2-sphinx
- ElasticSearch: через yii \asticsearch \ ActiveRecord , требуется расширение
yii2-elasticsearch
И следующие базы данных NoSQL:
- Redis 2.6.12 или более поздней версии : через yii \ redis \ ActiveRecord , требуется расширение
yii2-redis
- MongoDB 1.3.0 или более поздней версии : через yii \ mongodb \ ActiveRecord , требуется расширение
yii2-mongodb
Изучение Основ
В предыдущем выпуске « Как программировать на Yii2: работа с базой данных и активной записью» я прошел через создание базы данных, как Yii подключается к ней для каждого сеанса, с помощью миграции для создания таблиц базы данных и с помощью Gii (полезный код Yii). генератор строительных лесов) для создания кода модели по умолчанию. Если вы не знакомы с этим, просмотрите этот эпизод.
В этом выпуске я сосредоточусь больше на использовании Active Record в вашем коде.
Объявление класса активной записи в модели
Во-первых, давайте рассмотрим, как преобразовать модель Yii для использования Active Record. Я буду использовать пример модели, которую я создал в серии Building Your Startup . Из этой серии вы узнаете, как я создаю свой стартап, Meeting Planner , в Yii2.
Я буду использовать пример простой модели, которую я создал, под названием Launch, которая позволяет посетителям домашней страницы предоставлять свой адрес электронной почты, если они хотят получать уведомления, когда продукт выходит из предварительного просмотра и полностью выпущен.
Использовать Active Record с моделью довольно просто; обратите внимание, что class Launch extends \yii\db\ActiveRecord
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
<?php
namespace frontend\models;
use Yii;
use yii\db\ActiveRecord;
/**
* This is the model class for table «launch».
*
* @property integer $id
* @property string $email
* @property string $ip_addr
* @property integer $status
* @property integer $created_at
* @property integer $updated_at
*/
class Launch extends \yii\db\ActiveRecord
{
const STATUS_REQUEST =0;
/**
* @inheritdoc
*/
public static function tableName()
{
return ‘launch’;
}
|
Вот и все.
Построение запросов
Давайте посмотрим на некоторые распространенные запросы Active Record.
Индивидуальные записи
Если у вас есть идентификатор записи, часто из параметра запроса от контроллера, легко найти нужную запись:
1
2
3
|
public function actionSomething($id)
{
$model = Launch::findOne($id);
|
Это идентично:
1
2
3
|
$model = Launch::find()
->where([‘id’ => $id])
->one();
|
Вы также можете расширить массив ->where
дополнительными полями или логическими условиями:
01
02
03
04
05
06
07
08
09
10
|
$model = Launch::find()
->where([‘id’ => $id,’status’=>Launch::ACTIVE_REQUEST])
…
//equivalent to
$model = Launch::find()
->where([‘id’ => $id)
->andWhere([‘status’=>Launch::ACTIVE_REQUEST])
->orWhere([‘status’=>Launch::FUTURE_REQUEST])
…
|
Несколько записей
Вот пример поиска всех записей, которые соответствуют определенному status
отсортированных по $id
:
1
2
3
4
|
$people = Launch::find()
->where([‘status’ => Launch::STATUS_REQUEST])
->orderBy(‘id’)
->all();
|
->all();
находит все записи вместо одной. Переменная $people
возвращается как массив объектов модели. Кроме того, когда нет условий, вы можете получить доступ ко всем записям с помощью ->findAll();
Возвращение массива
Использование indexBy
возвращает массив элементов, проиндексированных по их id
:
1
2
3
|
$people = Launch::find()
->indexBy(‘id’)
->all();
|
Кроме того, вы можете вернуть ассоциативный массив с помощью ->asArray()
:
1
2
3
|
$people = Launch::find()
->asArray()
->all();
|
Примечание. Документация Yii гласит: «Хотя этот метод экономит память и повышает производительность, он ближе к нижнему уровню абстракции БД, и вы потеряете большинство функций Active Record».
Подсчет записей
Вы также можете вернуть только count
из запроса:
1
2
3
|
$count = Launch::find()
->where([‘status’ => Launch::STATUS_REQUEST])
->count();
|
Например, я часто использую счетчики в Meeting Planner для статистики; узнать больше в нашем эпизоде Dashboard :
1
2
3
4
5
6
7
8
|
// calculate $count_meetings_completed
$hd->count_meetings_completed = Meeting::find()->where([‘status’=>Meeting::STATUS_COMPLETED])->andWhere(‘created_at<‘.$since)->count();;
// calculate $count_meetings_expired
$hd->count_meetings_expired = Meeting::find()->where([‘status’=>Meeting::STATUS_EXPIRED])->andWhere(‘created_at<‘.$since)->count();;
// calculate $count_meetings_planning
$hd->count_meetings_planning = Meeting::find()->where(‘status<‘.Meeting::STATUS_COMPLETED)->andWhere(‘created_at<‘.$since)->count();;
// calculate $count_places
$hd->count_places = Place::find()->where(‘created_at>’.$after)->andWhere(‘created_at<‘.$since)->count();
|
Доступ к данным
После того, как вы запросили данные, такие как отдельная модель, легко получить доступ к данным как к объекту модели:
1
2
3
|
$model = Launch::findOne($id);
$id = $model->id;
$email = $model->email;
|
Я часто обрабатываю массивы так:
1
2
3
4
|
$users = User::findAll();
foreach ($users as $u) {
$id = $u->id;
$email = $u->email;
|
Massive Assignment
Вы также можете быстро назначить массив записи модели через ActiveRecord:
1
2
3
4
5
6
7
|
$values = [
‘name’ => ‘James’,
’email’ => ‘[email protected]’,
];
$customer = new Customer();
$customer->attributes = $values;
$customer->save();
|
Это часто используется для заполнения данных модели после отправки формы :
1
2
3
4
5
6
|
if (isset($_POST[‘FormName’])) {
$model->attributes = $_POST[‘FormName’];
if ($model->save()) {
// handle success
}
}
|
Или вы можете использовать ->load()
для этого:
1
2
3
|
if ($model->load(Yii::$app->request->post()) && $model->save()) {
…
}
|
Генератор кода Gii из Yii прекрасно подходит для генерации моделей с использованием ActiveRecord, которые делают это за вас, например, модели, контроллеры, формы, представления и т. Д.
Сохранение данных
Как вы можете видеть выше, сохранение данных с помощью Active Record также легко. В этом примере из документации по Yii создается и сохраняется новая запись, а затем запись загружается по id и сохраняются обновления:
01
02
03
04
05
06
07
08
09
10
|
// insert a new row of data
$customer = new Customer();
$customer->name = ‘James’;
$customer->email = ‘[email protected]’;
$customer->save();
// update an existing row of data
$customer = Customer::findOne(123);
$customer->email = ‘[email protected]’;
$customer->save();
|
Удаление записей
Удалить запись еще проще:
1
2
|
$u = User::findOne(99);
$u->delete();
|
Обновление счетчиков
Yii также предлагает простой счетчик приращений. Допустим, пользователь планирует другое собрание, и я отслеживаю, сколько в пользовательской таблице:
1
2
3
4
|
$u = User::findOne(99);
$u->updateCounters([‘meeting_count’=>1]);
// equivalent to
// UPDATE `User` SET `meeting_count` = `meeting_count` + 1 WHERE `id` = 99
|
связи
Соединение таблиц между индексами — одна из самых мощных возможностей Active Record. Например, в Планировщике собраний каждое собрание может иметь 0 или более мест MeetingPlaces
. Модель Meeting.php определяет для этого реляционный ActiveQuery:
1
2
3
4
5
6
7
8
|
* @property MeetingPlace[] $meetingPlaces
/**
* @return \yii\db\ActiveQuery
*/
public function getMeetingPlaces()
{
return $this->hasMany(MeetingPlace::className(), [‘meeting_id’ => ‘id’]);
}
|
Затем я могу получить доступ ко всем местам встречи с $meetingPlaces
свойства $meetingPlaces
. Ниже я загружаю собрание и перебираю все его meetingPlaces
довольно легко, как если бы это был встроенный массив meetingPlaces
:
1
2
3
4
|
$mtg=Meeting::find()->where([‘id’=>$meeting_id])->one();
foreach ($mtg->meetingPlaces as $mp) {
…
}
|
Конечно, это зависит от создания внешнего ключа при создании таблицы при ее миграции:
01
02
03
04
05
06
07
08
09
10
11
12
|
$this->createTable(‘{{%meeting_place}}’, [
‘id’ => Schema::TYPE_PK,
‘meeting_id’ => Schema::TYPE_INTEGER.’
‘place_id’ => Schema::TYPE_INTEGER.’
‘suggested_by’ => Schema::TYPE_BIGINT.’
‘status’ => Schema::TYPE_SMALLINT .
‘created_at’ => Schema::TYPE_INTEGER .
‘updated_at’ => Schema::TYPE_INTEGER .
], $tableOptions);
$this->addForeignKey(‘fk_meeting_place_meeting’,
‘{{%meeting_place}}’, ‘meeting_id’, ‘{{%meeting}}’,
‘id’, ‘CASCADE’, ‘CASCADE’);
|
Что дальше
Я надеюсь, что это дало легкое введение в удивительность Active Record. Сюда также входят жизненные циклы, транзакции и блокировки, о которых я могу написать в будущем. Если вы хотите двигаться вперед, Yii2 предлагает две отличные области для получения дополнительной информации в своей документации: Руководство по активной записи Yii2 и функциональные спецификации активной записи Yii2 . Это хорошо написанные введения.
Следите за будущими уроками в серии « Программирование с Yii2», поскольку мы продолжаем изучать различные аспекты фреймворка. Вы также можете проверить вышеупомянутую серию «Создание стартапа на PHP» .
Если вы хотите узнать, когда появится следующий учебник по Yii2, следуйте за мной @reifman в Твиттере или зайдите на страницу моего инструктора .