HLEB2 FAQ: Как использовать ORM для фреймворка? Вопрос

27 Мая (ред)

К фреймворку прилагается класс DB для выполнения запросов к базе данных, это простая обёртка над PHP PDO и не является ORM (объектно-реляционным отображением). Поэтому, чтобы подключить стороннюю ORM в проект с фреймворком HLEB2 нужно следовать трём простым пунктам:

  1. Выбрать и установить подходящую ORM.
  2. Задать в конфигурации настройки для этой ORM.
  3. Создать сервис для 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;
    }
}
fomiash fomiash + 215
Опубликовано в PHP фреймворк HLEB
К сожалению, ответов пока нет


Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.