Flight Active Record
Active Record — это сопоставление сущности базы данных с объектом PHP. Проще говоря, если у вас есть таблица users в базе данных, вы можете "перевести" строку в этой таблице в класс User и объект $user в вашем коде. См. базовый пример.
Нажмите здесь для просмотра репозитория на GitHub.
Базовый пример
Предположим, у вас есть следующая таблица:
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT,
password TEXT
);Теперь вы можете настроить новый класс для представления этой таблицы:
/**
* Класс ActiveRecord обычно используется в единственном числе
*
* Настоятельно рекомендуется добавлять свойства таблицы в виде комментариев здесь
*
* @property int $id
* @property string $name
* @property string $password
*/
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
// вы можете установить это таким образом
parent::__construct($database_connection, 'users');
// или таким образом
parent::__construct($database_connection, null, [ 'table' => 'users']);
}
}Теперь наблюдайте за магией!
// для sqlite
$database_connection = new PDO('sqlite:test.db'); // это просто для примера, вы, вероятно, используете реальное соединение с базой данных
// для mysql
$database_connection = new PDO('mysql:host=localhost;dbname=test_db&charset=utf8bm4', 'username', 'password');
// или mysqli
$database_connection = new mysqli('localhost', 'username', 'password', 'test_db');
// или mysqli с созданием на основе не-объекта
$database_connection = mysqli_connect('localhost', 'username', 'password', 'test_db');
$user = new User($database_connection);
$user->name = 'Bobby Tables';
$user->password = password_hash('some cool password');
$user->insert();
// или $user->save();
echo $user->id; // 1
$user->name = 'Joseph Mamma';
$user->password = password_hash('some cool password again!!!');
$user->insert();
// здесь нельзя использовать $user->save(), иначе оно подумает, что это обновление!
echo $user->id; // 2И было так просто добавить нового пользователя! Теперь, когда в базе данных есть строка пользователя, как вы её извлечёте?
$user->find(1); // найти id = 1 в базе данных и вернуть его.
echo $user->name; // 'Bobby Tables'А что, если вы хотите найти всех пользователей?
$users = $user->findAll();А с определённым условием?
$users = $user->like('name', '%mamma%')->findAll();Видите, насколько это весело? Давайте установим его и начнём!
Установка
Просто установите с помощью Composer
composer require flightphp/active-record Использование
Это можно использовать как самостоятельную библиотеку или с фреймворком Flight PHP. Полностью на ваше усмотрение.
Автономно
Просто убедитесь, что вы передаёте соединение PDO в конструктор.
$pdo_connection = new PDO('sqlite:test.db'); // это просто для примера, вы, вероятно, используете реальное соединение с базой данных
$User = new User($pdo_connection);Не хотите всегда устанавливать соединение с базой данных в конструкторе? См. Управление соединением с базой данных для других идей!
Регистрация как метода в Flight
Если вы используете фреймворк Flight PHP, вы можете зарегистрировать класс ActiveRecord как сервис, но честно говоря, это не обязательно.
Flight::register('user', 'User', [ $pdo_connection ]);
// затем вы можете использовать его так в контроллере, функции и т.д.
Flight::user()->find(1);Методы runway
runway — это CLI-инструмент для Flight, который имеет пользовательскую команду для этой библиотеки.
# Использование
php runway make:record database_table_name [class_name]
# Пример
php runway make:record usersЭто создаст новый класс в директории app/records/ как UserRecord.php со следующим содержимым:
<?php
declare(strict_types=1);
namespace app\records;
/**
* Класс ActiveRecord для таблицы users.
* @link https://docs.flightphp.com/awesome-plugins/active-record
*
* @property int $id
* @property string $username
* @property string $email
* @property string $password_hash
* @property string $created_dt
*/
class UserRecord extends \flight\ActiveRecord
{
/**
* @var array $relations Установка отношений для модели
* https://docs.flightphp.com/awesome-plugins/active-record#relationships
*/
protected array $relations = [
// 'relation_name' => [ self::HAS_MANY, 'RelatedClass', 'foreign_key' ],
];
/**
* Конструктор
* @param mixed $databaseConnection Соединение с базой данных
*/
public function __construct($databaseConnection)
{
parent::__construct($databaseConnection, 'users');
}
}Функции CRUD
find($id = null) : boolean|ActiveRecord
Найти одну запись и присвоить её текущему объекту. Если вы передадите $id какого-либо рода, он выполнит поиск по первичному ключу с этим значением. Если ничего не передано, он просто найдёт первую запись в таблице.
Кроме того, вы можете передать другие вспомогательные методы для запроса таблицы.
// найти запись с некоторыми условиями заранее
$user->notNull('password')->orderBy('id DESC')->find();
// найти запись по конкретному id
$id = 123;
$user->find($id);findAll(): array<int,ActiveRecord>
Находит все записи в указанной таблице.
$user->findAll();isHydrated(): boolean (v0.4.0)
Возвращает true, если текущая запись была гидратирована (загружена из базы данных).
$user->find(1);
// если запись найдена с данными...
$user->isHydrated(); // trueinsert(): boolean|ActiveRecord
Вставляет текущую запись в базу данных.
$user = new User($pdo_connection);
$user->name = 'demo';
$user->password = md5('demo');
$user->insert();Первичные ключи на основе текста
Если у вас есть первичный ключ на основе текста (например, UUID), вы можете установить значение первичного ключа перед вставкой одним из двух способов.
$user = new User($pdo_connection, [ 'primaryKey' => 'uuid' ]);
$user->uuid = 'some-uuid';
$user->name = 'demo';
$user->password = md5('demo');
$user->insert(); // или $user->save();или вы можете позволить первичному ключу генерироваться автоматически для вас через события.
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users', [ 'primaryKey' => 'uuid' ]);
// вы также можете установить primaryKey таким образом вместо массива выше.
$this->primaryKey = 'uuid';
}
protected function beforeInsert(self $self) {
$self->uuid = uniqid(); // или как вам нужно генерировать уникальные id
}
}Если вы не установите первичный ключ перед вставкой, он будет установлен как rowid, и база данных сгенерирует его для вас, но он не сохранится, потому что это поле может не существовать в вашей таблице. Поэтому рекомендуется использовать событие для автоматической обработки этого.
update(): boolean|ActiveRecord
Обновляет текущую запись в базе данных.
$user->greaterThan('id', 0)->orderBy('id desc')->find();
$user->email = 'test@example.com';
$user->update();save(): boolean|ActiveRecord
Вставляет или обновляет текущую запись в базу данных. Если запись имеет id, она обновится, иначе вставится.
$user = new User($pdo_connection);
$user->name = 'demo';
$user->password = md5('demo');
$user->save();Примечание: Если у вас определены отношения в классе, он рекурсивно сохранит эти отношения, если они определены, инстанцированы и имеют изменённые данные для обновления. (v0.4.0 и выше)
delete(): boolean
Удаляет текущую запись из базы данных.
$user->gt('id', 0)->orderBy('id desc')->find();
$user->delete();Вы также можете удалить несколько записей, выполнив поиск заранее.
$user->like('name', 'Bob%')->delete();dirty(array $dirty = []): ActiveRecord
Грязные данные относятся к данным, которые были изменены в записи.
$user->greaterThan('id', 0)->orderBy('id desc')->find();
// на данный момент ничего не "грязное".
$user->email = 'test@example.com'; // теперь email считается "грязным", поскольку оно изменилось.
$user->update();
// теперь нет данных, которые являются грязными, потому что они обновлены и сохранены в базе данных
$user->password = password_hash()'newpassword'); // теперь это грязное
$user->dirty(); // передача ничего очистит все грязные записи.
$user->update(); // ничего не обновится, потому что ничего не было захвачено как грязное.
$user->dirty([ 'name' => 'something', 'password' => password_hash('a different password') ]);
$user->update(); // и name, и password обновлены.copyFrom(array $data): ActiveRecord (v0.4.0)
Это псевдоним для метода dirty(). Это немного яснее, что вы делаете.
$user->copyFrom([ 'name' => 'something', 'password' => password_hash('a different password') ]);
$user->update(); // и name, и password обновлены.isDirty(): boolean (v0.4.0)
Возвращает true, если текущая запись была изменена.
$user->greaterThan('id', 0)->orderBy('id desc')->find();
$user->email = 'test@email.com';
$user->isDirty(); // truereset(bool $include_query_data = true): ActiveRecord
Сбрасывает текущую запись в её начальное состояние. Это очень полезно для циклов. Если вы передадите true, он также сбросит данные запроса, которые использовались для поиска текущего объекта (поведение по умолчанию).
$users = $user->greaterThan('id', 0)->orderBy('id desc')->find();
$user_company = new UserCompany($pdo_connection);
foreach($users as $user) {
$user_company->reset(); // начать с чистого листа
$user_company->user_id = $user->id;
$user_company->company_id = $some_company_id;
$user_company->insert();
}getBuiltSql(): string (v0.4.1)
После выполнения метода find(), findAll(), insert(), update() или save() вы можете получить построенный SQL и использовать его для отладки.
Методы SQL-запросов
select(string $field1 [, string $field2 ... ])
Вы можете выбрать только несколько столбцов в таблице, если хотите (это более производительно для очень широких таблиц с многими столбцами)
$user->select('id', 'name')->find();from(string $table)
Вы технически можете выбрать другую таблицу тоже! Почему бы и нет?!
$user->select('id', 'name')->from('user')->find();join(string $table_name, string $join_condition)
Вы даже можете присоединить другую таблицу в базе данных.
$user->join('contacts', 'contacts.user_id = users.id')->find();where(string $where_conditions)
Вы можете установить некоторые пользовательские аргументы where (вы не можете установить параметры в этом операторе where)
$user->where('id=1 AND name="demo"')->find();Примечание по безопасности — Вас может соблазнить сделать что-то вроде $user->where("id = '{$id}' AND name = '{$name}'")->find();. Пожалуйста, НЕ ДЕЛАЙТЕ ЭТОГО!!! Это подвержено тому, что известно как атаки SQL-инъекций. В интернете много статей, пожалуйста, погуглите "sql injection attacks php" и вы найдёте много статей по этой теме. Правильный способ обработки этого с этой библиотекой — вместо этого метода where() вы бы сделали что-то вроде $user->eq('id', $id)->eq('name', $name)->find(); Если вам абсолютно необходимо это сделать, библиотека PDO имеет $pdo->quote($var) для экранирования. Только после использования quote() вы можете использовать его в операторе where().
group(string $group_by_statement)/groupBy(string $group_by_statement)
Группируйте ваши результаты по определённому условию.
$user->select('COUNT(*) as count')->groupBy('name')->findAll();order(string $order_by_statement)/orderBy(string $order_by_statement)
Сортируйте возвращаемый запрос определённым образом.
$user->orderBy('name DESC')->find();limit(string $limit)/limit(int $offset, int $limit)
Ограничьте количество возвращаемых записей. Если дано второе целое число, оно будет offset, limit точно как в SQL.
$user->orderby('name DESC')->limit(0, 10)->findAll();Условия WHERE
equal(string $field, mixed $value) / eq(string $field, mixed $value)
Где field = $value
$user->eq('id', 1)->find();notEqual(string $field, mixed $value) / ne(string $field, mixed $value)
Где field <> $value
$user->ne('id', 1)->find();isNull(string $field)
Где field IS NULL
$user->isNull('id')->find();isNotNull(string $field) / notNull(string $field)
Где field IS NOT NULL
$user->isNotNull('id')->find();greaterThan(string $field, mixed $value) / gt(string $field, mixed $value)
Где field > $value
$user->gt('id', 1)->find();lessThan(string $field, mixed $value) / lt(string $field, mixed $value)
Где field < $value
$user->lt('id', 1)->find();greaterThanOrEqual(string $field, mixed $value) / ge(string $field, mixed $value) / gte(string $field, mixed $value)
Где field >= $value
$user->ge('id', 1)->find();lessThanOrEqual(string $field, mixed $value) / le(string $field, mixed $value) / lte(string $field, mixed $value)
Где field <= $value
$user->le('id', 1)->find();like(string $field, mixed $value) / notLike(string $field, mixed $value)
Где field LIKE $value или field NOT LIKE $value
$user->like('name', 'de')->find();in(string $field, array $values) / notIn(string $field, array $values)
Где field IN($value) или field NOT IN($value)
$user->in('id', [1, 2])->find();between(string $field, array $values)
Где field BETWEEN $value AND $value1
$user->between('id', [1, 2])->find();Условия OR
Возможно обернуть ваши условия в оператор OR. Это делается либо с помощью метода startWrap() и endWrap(), либо заполняя 3-й параметр условия после поля и значения.
// Метод 1
$user->eq('id', 1)->startWrap()->eq('name', 'demo')->or()->eq('name', 'test')->endWrap('OR')->find();
// Это вычислится как `id = 1 AND (name = 'demo' OR name = 'test')`
// Метод 2
$user->eq('id', 1)->eq('name', 'demo', 'OR')->find();
// Это вычислится как `id = 1 OR name = 'demo'`Отношения
Вы можете установить несколько видов отношений с помощью этой библиотеки. Вы можете установить отношения один-ко-многим и один-к-одному между таблицами. Это требует немного дополнительной настройки в классе заранее.
Установка массива $relations не сложна, но угадывание правильного синтаксиса может быть запутанным.
protected array $relations = [
// вы можете назвать ключ как угодно. Название ActiveRecord, вероятно, хорошо. Пример: user, contact, client
'user' => [
// обязательно
// self::HAS_MANY, self::HAS_ONE, self::BELONGS_TO
self::HAS_ONE, // это тип отношения
// обязательно
'Some_Class', // это "другой" класс ActiveRecord, на который будет ссылка
// обязательно
// в зависимости от типа отношения
// self::HAS_ONE = внешний ключ, который ссылается на соединение
// self::HAS_MANY = внешний ключ, который ссылается на соединение
// self::BELONGS_TO = локальный ключ, который ссылается на соединение
'local_or_foreign_key',
// просто FYI, это также присоединяется только к первичному ключу "другой" модели
// опционально
[ 'eq' => [ 'client_id', 5 ], 'select' => 'COUNT(*) as count', 'limit' 5 ], // дополнительные условия, которые вы хотите при присоединении отношения
// $record->eq('client_id', 5)->select('COUNT(*) as count')->limit(5))
// опционально
'back_reference_name' // это если вы хотите обратную ссылку на это отношение обратно на себя Пример: $user->contact->user;
];
]class User extends ActiveRecord{
protected array $relations = [
'contacts' => [ self::HAS_MANY, Contact::class, 'user_id' ],
'contact' => [ self::HAS_ONE, Contact::class, 'user_id' ],
];
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
}
class Contact extends ActiveRecord{
protected array $relations = [
'user' => [ self::BELONGS_TO, User::class, 'user_id' ],
'user_with_backref' => [ self::BELONGS_TO, User::class, 'user_id', [], 'contact' ],
];
public function __construct($database_connection)
{
parent::__construct($database_connection, 'contacts');
}
}Теперь у нас настроены ссылки, чтобы мы могли использовать их очень легко!
$user = new User($pdo_connection);
// найти самого последнего пользователя.
$user->notNull('id')->orderBy('id desc')->find();
// получить контакты, используя отношение:
foreach($user->contacts as $contact) {
echo $contact->id;
}
// или мы можем пойти в обратную сторону.
$contact = new Contact();
// найти один контакт
$contact->find();
// получить пользователя, используя отношение:
echo $contact->user->name; // это имя пользователяДовольно круто, eh?
Жадная загрузка
Обзор
Жадная загрузка решает проблему N+1 запросов, загружая отношения заранее. Вместо выполнения отдельного запроса для отношений каждой записи, жадная загрузка извлекает все связанные данные всего в одном дополнительном запросе на отношение.
Примечание: Жадная загрузка доступна только для v0.7.0 и выше.
Базовое использование
Используйте метод with() для указания, какие отношения жадно загружать:
// Загрузить пользователей с их контактами в 2 запроса вместо N+1
$users = $user->with('contacts')->findAll();
foreach ($users as $u) {
foreach ($u->contacts as $contact) {
echo $contact->email; // Нет дополнительного запроса!
}
}Несколько отношений
Загружайте несколько отношений одновременно:
$users = $user->with(['contacts', 'profile', 'settings'])->findAll();Типы отношений
HAS_MANY
// Жадно загрузить все контакты для каждого пользователя
$users = $user->with('contacts')->findAll();
foreach ($users as $u) {
// $u->contacts уже загружен как массив
foreach ($u->contacts as $contact) {
echo $contact->email;
}
}HAS_ONE
// Жадно загрузить один контакт для каждого пользователя
$users = $user->with('contact')->findAll();
foreach ($users as $u) {
// $u->contact уже загружен как объект
echo $u->contact->email;
}BELONGS_TO
// Жадно загрузить родительских пользователей для всех контактов
$contacts = $contact->with('user')->findAll();
foreach ($contacts as $c) {
// $c->user уже загружен
echo $c->user->name;
}С find()
Жадная загрузка работает как с findAll() , так и с find() :
$user = $user->with('contacts')->find(1);
// Пользователь и все их контакты загружены в 2 запросаПреимущества производительности
Без жадной загрузки (проблема N+1):
$users = $user->findAll(); // 1 запрос
foreach ($users as $u) {
$contacts = $u->contacts; // N запросов (по одному на пользователя!)
}
// Итого: 1 + N запросовС жадной загрузкой:
$users = $user->with('contacts')->findAll(); // всего 2 запроса
foreach ($users as $u) {
$contacts = $u->contacts; // 0 дополнительных запросов!
}
// Итого: 2 запроса (1 для пользователей + 1 для всех контактов)Для 10 пользователей это уменьшает запросы с 11 до 2 — снижение на 82%!
Важные примечания
- Жадная загрузка полностью опциональна — ленивая загрузка работает как раньше
- Уже загруженные отношения автоматически пропускаются
- Обратные ссылки работают с жадной загрузкой
- Колбэки отношений уважаются во время жадной загрузки
Ограничения
- Вложенная жадная загрузка (например, with(['contacts.addresses']) ) в настоящее время не поддерживается
- Ограничения жадной загрузки через замыкания не поддерживаются в этой версии
Установка пользовательских данных
Иногда вам может понадобиться прикрепить что-то уникальное к вашему ActiveRecord, например, пользовательский расчёт, который может быть проще прикрепить к объекту, который затем передаётся, скажем, в шаблон.
setCustomData(string $field, mixed $value)
Вы прикрепляете пользовательские данные с помощью метода setCustomData().
$user->setCustomData('page_view_count', $page_view_count);А затем вы просто ссылаетесь на него как на обычное свойство объекта.
echo $user->page_view_count;События
Ещё одна супер крутая функция этой библиотеки — это события. События срабатывают в определённые моменты на основе определённых методов, которые вы вызываете. Они очень полезны для автоматической настройки данных для вас.
onConstruct(ActiveRecord $ActiveRecord, array &config)
Это очень полезно, если вам нужно установить соединение по умолчанию или что-то вроде того.
// index.php или bootstrap.php
Flight::register('db', 'PDO', [ 'sqlite:test.db' ]);
//
//
//
// User.php
class User extends flight\ActiveRecord {
protected function onConstruct(self $self, array &$config) { // не забудьте ссылку &
// вы могли бы сделать это для автоматической установки соединения
$config['connection'] = Flight::db();
// или это
$self->transformAndPersistConnection(Flight::db());
// Вы также можете установить имя таблицы таким образом.
$config['table'] = 'users';
}
}beforeFind(ActiveRecord $ActiveRecord)
Это, вероятно, полезно только если вам нужно манипулировать запросом каждый раз.
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function beforeFind(self $self) {
// всегда выполняйте id >= 0, если это ваш стиль
$self->gte('id', 0);
}
}afterFind(ActiveRecord $ActiveRecord)
Этот, вероятно, более полезен, если вам всегда нужно выполнять некоторую логику каждый раз, когда эта запись извлекается. Нужно ли вам расшифровать что-то? Нужно ли выполнять пользовательский запрос подсчёта каждый раз (не производительно, но ладно)?
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function afterFind(self $self) {
// расшифровка чего-то
$self->secret = yourDecryptFunction($self->secret, $some_key);
// возможно, хранение чего-то пользовательского, как запрос???
$self->setCustomData('view_count', $self->select('COUNT(*) count')->from('user_views')->eq('user_id', $self->id)['count'];
}
}beforeFindAll(ActiveRecord $ActiveRecord)
Это, вероятно, полезно только если вам нужно манипулировать запросом каждый раз.
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function beforeFindAll(self $self) {
// всегда выполняйте id >= 0, если это ваш стиль
$self->gte('id', 0);
}
}afterFindAll(array<int,ActiveRecord> $results)
Похоже на afterFind(), но вы можете сделать это для всех записей!
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function afterFindAll(array $results) {
foreach($results as $self) {
// сделайте что-то крутое, как afterFind()
}
}
}beforeInsert(ActiveRecord $ActiveRecord)
Очень полезно, если вам нужно установить некоторые значения по умолчанию каждый раз.
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function beforeInsert(self $self) {
// установите некоторые разумные значения по умолчанию
if(!$self->created_date) {
$self->created_date = gmdate('Y-m-d');
}
if(!$self->password) {
$self->password = password_hash((string) microtime(true));
}
}
}afterInsert(ActiveRecord $ActiveRecord)
Возможно, у вас есть случай использования для изменения данных после вставки?
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function afterInsert(self $self) {
// делайте, что хотите
Flight::cache()->set('most_recent_insert_id', $self->id);
// или что угодно....
}
}beforeUpdate(ActiveRecord $ActiveRecord)
Очень полезно, если вам нужно установить некоторые значения по умолчанию каждый раз при обновлении.
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function beforeInsert(self $self) {
// установите некоторые разумные значения по умолчанию
if(!$self->updated_date) {
$self->updated_date = gmdate('Y-m-d');
}
}
}afterUpdate(ActiveRecord $ActiveRecord)
Возможно, у вас есть случай использования для изменения данных после обновления?
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function afterInsert(self $self) {
// делайте, что хотите
Flight::cache()->set('most_recently_updated_user_id', $self->id);
// или что угодно....
}
}beforeSave(ActiveRecord $ActiveRecord)/afterSave(ActiveRecord $ActiveRecord)
Это полезно, если вы хотите, чтобы события происходили как при вставках, так и при обновлениях. Я пощажу вас от длинного объяснения, но уверен, вы можете угадать, что это такое.
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function beforeSave(self $self) {
$self->last_updated = gmdate('Y-m-d H:i:s');
}
}beforeDelete(ActiveRecord $ActiveRecord)/afterDelete(ActiveRecord $ActiveRecord)
Не уверен, что вы захотите здесь сделать, но никаких суждений! Действуйте!
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function beforeDelete(self $self) {
echo 'He was a brave soldier... :cry-face:';
}
}Управление соединением с базой данных
При использовании этой библиотеки вы можете установить соединение с базой данных несколькими способами. Вы можете установить соединение в конструкторе, вы можете установить его через переменную конфигурации $config['connection'] или вы можете установить его через setDatabaseConnection() (v0.4.1).
$pdo_connection = new PDO('sqlite:test.db'); // для примера
$user = new User($pdo_connection);
// или
$user = new User(null, [ 'connection' => $pdo_connection ]);
// или
$user = new User();
$user->setDatabaseConnection($pdo_connection);Если вы хотите избежать установки $database_connection каждый раз при вызове active record, есть способы обойти это!
// index.php или bootstrap.php
// Установите это как зарегистрированный класс в Flight
Flight::register('db', 'PDO', [ 'sqlite:test.db' ]);
// User.php
class User extends flight\ActiveRecord {
public function __construct(array $config = [])
{
$database_connection = $config['connection'] ?? Flight::db();
parent::__construct($database_connection, 'users', $config);
}
}
// И теперь аргументы не требуются!
$user = new User();Примечание: Если вы планируете unit-тестирование, делать это таким образом может добавить некоторые вызовы для unit-тестирования, но в целом, поскольку вы можете инжектировать ваше соединение с
setDatabaseConnection()или$config['connection'], это не так плохо.
Если вам нужно обновить соединение с базой данных, например, если вы запускаете длительный CLI-скрипт и нужно обновлять соединение каждые несколько минут, вы можете переустановить соединение с $your_record->setDatabaseConnection($pdo_connection).
Вклад
Пожалуйста, сделайте. :D
Настройка
При вкладе убедитесь, что вы запускаете composer test-coverage для поддержания 100% покрытия тестами (это не настоящее покрытие unit-тестами, больше как интеграционное тестирование).
Также убедитесь, что вы запускаете composer beautify и composer phpcs для исправления любых ошибок линтинга.
Лицензия
MIT