@kanstantsin

Плохая ли это идея конфигурировать классы/сервисы с помощью замыканий, а не, например, массивов?

Во многих библиотеках есть возможность загрузить конфигурацию из массива (или любого файла конфигурации). Не будет ли лучшей идеей конфигурировать сервис замыканием или любым другим вызываемым объектом (Class::__invoke(), например)?

Для иллюстрации:

class Router 
{
    public function __construct(Closure $config)
    {
        $closure($this);
    }

    public function addRoute(...$params) {
        // some code
    }
}


Конфигурация выглядит так:

return function($router) {

    $router
        ->addRoute('/')
        ->setName('home')
    ;

    // and so on....        
}


И, наконец, вызов сервиса:

$router = new Router(include 'config/router.php');
$controller = $router->match('/some/path');


Не будет ли это проще, чем загружать статическую конфигурацию и разбирать эту конфигурацию уже в сервисе, вызывая публичные методы и по сути делая тоже самое?

UPD: убрал упоминание фреймворков, чтобы не вводить в заблуждение. Речь идет о библиотеках/компонентах без внешних зависимостей.
  • Вопрос задан
  • 265 просмотров
Пригласить эксперта
Ответы на вопрос 2
27cm
@27cm
TODO: Написать статус
Нет, не лучше.

Конфиги бывает нужно мёрджить, кешировать и т. д. В том же ZF2 конфиг одного модуля может переопределять значения другого или даже глобальные настройки приложения. С замыканиями это будет не так просто.

Но даже, если и делать так, то уж идти ещё дальше, до конца, просто создавать наследника class MyRoute extends Route и в итоге код будет проще:
$router = new MyRoute();
$controller = $router->match('/some/path');


Мне кажется, что правильно, это когда конфигурационный файл содержит только значения настроек и ничего не знает о том, кто и как эти значения будет использовать. В вашем случае получается, что конфигурационный файл предоставляет замыкание для настройки объекта класса Router.
Ответ написан
mr_T
@mr_T
Web-разработчик
Выглядит неплохо, но лучше передавать функцию не в конструктор, а в какой-нибудь метод. Тогда для конфигурируемых подобным образом классом можно будет использовать примесь, что-то типа такого:

trait ClosureConfigurable {
    public function configureWith(Closure $closure) {
        $closure($this);
    }
}


Таким образом конструктор не будет содержать дополнительный код, а логику работы примеси можно будет безболезненно менять и дополнять (например, ставить замыкания в очередь, передавать им дополнительные параметры, сделать условную конфигурацию и т.п.).
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы