К фреймворку прилагается класс DB для выполнения запросов к базе данных, это простая обёртка над PHP PDO и не является ORM (объектно-реляционным отображением). Поэтому, чтобы подключить стороннюю ORM в проект с фреймворком HLEB2 нужно следовать трём простым пунктам:
- Выбрать и установить подходящую ORM.
- Задать в конфигурации настройки для этой ORM.
- Создать сервис для ORM инициализированный с настройками из конфигурации.
На примере популярной ORM Eloquent.
Установка Eloquent
Через композер:
composer require illuminate/database
Параметры в конфигурации
В файле /config/database.php (и /config/database-local.php если присутствует) создайте отдельный блок в массиве 'db.settings.list' под названием 'mysql.orm' (если подключаете MySQL):
'db.settings.list' => [
'mysql.orm' => [
'driver' => 'mysql',
'host' => 'localhost',
'port' => 3306,
'database' => 'database',
'username' => 'root',
'password' => 'password',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
],
// ...
]
Внесите в блок настройки вашей БД согласно рекомендациям из инструкции ORM (они перенесены в исходном виде).
Создание сервиса
Новый сервис нужно добавить в контейнер. Про устройство контейнера в документации фреймворка.
Упрощённый код сервиса:
<?php
// /app/Bootstrap/Services/OrmService.php
namespace App\Bootstrap\Services;
use Hleb\Static\Settings;
use Illuminate\Database\Capsule\Manager as Capsule;
class OrmService
{
public function init(): Capsule
{
$capsule = new Capsule();
$config = Settings::getParam('database', 'db.settings.list')['mysql.orm'];
$capsule->addConnection($config);
$capsule->setAsGlobal(); // Указано как необязательный параметр, но без него не работает.
$capsule->bootEloquent();
return $capsule;
}
}
Добавим сервис в класс App\Bootstrap\ContainerFactory:
\Illuminate\Database\Capsule\Manager::class => (new App\Bootstrap\Services\OrmService())->init(),
Теперь этот сервис можно использовать из контейнера в Модели:
<?php
// /app/Models/UserModel.php
namespace App\Models;
use Hleb\Base\Model;
use Illuminate\Database\Capsule\Manager as Orm;
class UserModel extends Model
{
public static function getVoteUsers()
{
$orm = self::container()->get(Orm::class);
$users = $orm::table('users')->where('votes', '>', 100)->get();
return $users;
}
}
Логирование
Также есть возможность подключить логгер фреймворка или другой сторонний для логирования запросов к БД в режиме DEBUG. Для этого нужно использовать события из Illuminate для прослушивания запросов.
Для начала нужно подключить события:
composer require illuminate/events
Затем изменить класс сервиса подобным образом:
<?php
// /app/Bootstrap/Services/OrmService.php
namespace App\Bootstrap\Services;
use Hleb\Static\Settings;
use Hleb\Static\System;
use Illuminate\Database\Capsule\Manager as Capsule;
use Illuminate\Database\Events\QueryExecuted;
use Illuminate\Events\Dispatcher;
class OrmService
{
public function init(): Capsule
{
$capsule = new Capsule();
$config = Settings::getParam('database', 'db.settings.list')['mysql.orm'];
$capsule->addConnection($config);
// Используем события из Illuminate для прослушивания запросов
$events = new Dispatcher(new \Illuminate\Container\Container());
$capsule->setEventDispatcher($events);
// Только в отладочном режиме.
if (Settings::getParam('common', 'debug')) {
// Подписка на запросы для логирования
$events->listen(QueryExecuted::class, function ($query) use ($config) {
System::createCustomLog(
$query->sql,
$query->time / 1000,
[
'bindings' => $query->bindings,
'connection' => $query->connectionName,
],
$config['database'],
$config['driver'],
);
});
}
$capsule->setAsGlobal();
$capsule->bootEloquent();
return $capsule;
}
}
Теперь внешняя ORM работает аналогично встроенной, включается вывод в лог параметром 'db.log.enabled' в конфигурации /config/main.php (или /config/main-local.php если присутствует).
Использование Eloquent ORM
Также попробовал использование ORM на уровне модели. Для этого установил подключение не в сервисе, а глобально.
Для этой библиотеки есть дополнительные возможности инициализировать класс глобально с обращением к его статическим методам. В таком случае подход будет другим. Нужно создать php-файл с указанной инициализацией вместо Сервиса и добавить путь к файлу в параметр конфигурации "custom.function.files". В этом файле оказалось содержимое выше указанного метода OrmService::init (без return).
После этого нужно внести правки в Модель, унаследовав её от класса ORM, пример:
<?php
// /app/Models/User.php
namespace App\Models;
class User extends \Illuminate\Database\Eloquent\Model
{
public static function getAdmin()
{
$admin = self::where(['id' => 1])->get();
return $admin;
}
}