#php #laravel #laravel-7
#php #laravel #laravel-7
Вопрос:
У меня разные классы фильтров, и каждый класс имеет несколько методов фильтрации. Есть (пока) один случай, когда мне нужно применить фильтры из 2 классов. Что я сделал, так это то, что я создал другой класс с именем FilterManager, который хранит список всех классов фильтров, которые вам нужны, а затем выполняет итерацию по списку и применяет фильтры.
class ThreadFilters
{
protected $builder;
protected $supportedFilters = ['newThreads'];
public function newThreads($userId)
{
$this->builder->orderBy('created_at', 'DESC');
}
}
class FilterManager
{
protected $filters = [];
public function addFilter($filter)
{
$this->filters[] = $filter;
}
public function apply($builder)
{
foreach($this->filters as $filter)
{
$filter->builder = $builder;
foreach($filter->supportedFilters as $filterMethod)
{
$filter->$filterMethod()
}
$builder = $filter->builder;
}
}
}
Теперь в контроллере я могу сделать что-то вроде
Первый подход
class ThreadController(FilterManager $filterManager)
{
$filters = $filterManager->addFilter(new ThreadFilter());
$filters->apply($someBuilder);
}
С другой стороны, я мог бы использовать функцию приложения
app(ThreadFilters::class)
и в контейнере сервиса в принципе я мог бы сделать
$this->app->bind(ThreadFilters::class, function($app){
$filterManager = new FilterManager();
$filterManager->addFilter(new ThreadFilters());
return $filterManager;
});
и поэтому мой контроллер будет выглядеть так
Второй подход
class ThreadController()
{
$filters = app(ThreadFilters::class);
$filter->apply($someBuilder);
}
Мой вопрос в том, какое решение является хорошим / приемлемым.
При первом подходе вводится зависимость FilterManager, и контроллер должен добавить фильтры потоков
Во втором подходе зависимости не вводятся, и контроллер должен использовать контейнер службы, чтобы скрыть специфику и сделать контроллер менее осведомленным о фильтрах.
Комментарии:
1. Я не нахожу никакой практической разницы. Контроллер связан с потоковыми фильтрами в обоих случаях, и (из-за того, как работает Laravel) добавление или удаление введенного параметра в контроллер не сильно меняет ситуацию
2. @apokryfos Да, действительно, вы правы. Не могли бы вы перефразировать «добавление или удаление введенного параметра в контроллер ничего не меняет», потому что я этого не понял.
3. Если, например, у вас есть
function threadControllerRouteHandler(FilterManager $filterManager)
это вызывается через внедрение зависимостей, то вы можете свободно добавлять и удалять параметры без необходимости вносить какие-либо изменения где-либо еще, потому что все зависимости вводятся. В этом смысле не имеет значения, вводите ли вы их в тело метода самостоятельно или позволяете Laravel вводить их при вызове метода. Дело в том, что вы не нарушите другой код, если измените сигнатуру метода (что вызывает беспокойство при обычном вызове метода)4. @apokryfos если я правильно понимаю, вы говорите, что не имеет значения, использую ли я внедрение зависимостей, например
function controller(FilterManager $filterManager)
, или я использую метод app () для разрешения моих зависимостей, напримерapp(ThreadFilters::class)
, который в конечном итоге вернет FilterManager5. Лично я бы просто использовал именованную привязку, например
$this->app->bind('filters.thread', function ...)
, и вы также можете добавить другие. Каждый из них может возвращать диспетчер фильтров. Недостатком является то, что вы должны использоватьapp('filters.thread')
для этого, поскольку вы не можете ввести его через параметр. Вы также можете использовать что-то вродеapp()->makeWith(FilterManager::class, [ 'parameter' => 'parameter value' ])
, если хотите более контекстуальное разрешение