Stanislav
Konstantin
еще раз: пишите код текстом, не скринами
Konstantin
вдруг я захочу сейчас вам поправить кусок кода, я его перепечатать с экрана должен?
Stanislav
Да сейчас напишу
Konstantin
уважайте собеседников/коллег
Konstantin
для этого есть форматирование
Konstantin
protected function configure(): void
{
$this
->setName('demo:test')
->setDescription('Some dirty stuff here')
;
}
Konstantin
например вот, отлично читается
Stanislav
Смотрите вот это вот в репозитории
$dql = 'SELECT p FROM APP\Entity\Post p
WHERE p.photos IS NOT EMPTY';
$qb = $this->getEntityManager()->createQuery($dql);
return $qb->getResult();
Вот это в контроллере
Stanislav
Похоже я как-то не так скинул код
Konstantin
так вот, тут джойна не хватает.
select p, ph from App\Entity\Posts p JOIN p.photos ph where p.photos is not empty
Stanislav
Понял, спасибо, сейчас попробую
Konstantin
как на винде - не знаю, но поищите
Stanislav
У меня mint, поищу
Stanislav
Konstantin
таки почитайте доку 🙂
The Ant
В таком варианте можно указать часть аргументов и привязать к переменным некоторые? например я хочу убрать газл клиент дефолтный и логгер, но они идут первыми. Значит нада остальные просто привязать к переменным и всё. (только для этого класса).
В варианте с ямлом вроде легко делается. А тут чет...
Vlad
‘$param’ => service(‘ant’)
Anton
доброго дня , подскажите пожалуйста относительно реализации: допустим есть сервис Foo которому в констроктур приходит BarInterface
есть сервисы Bar1, Bar2 которые реализуют интерфейс BarInterface. и в зависимости от параметра http реквеста инжектятся в Foo
Иван
Юра
Иван
Фактори сервис
да, но нет
потому что фактори будет явно зависеть от реквеста где-то в недрах
Иван
а всё, что касается реквеста, должно происходить рядом с контроллером
Юра
Хз откуда такие умозаключения
Сергей
Делаешь BarProvider. В него добавляешь свои сервисы. И в методе getService() получаешь нужный сервис. У каждого сервиса есть метод - supports.
В supports проверяешь условия для выбора этого сервиса.
Инжектишь этого провайдера в нужное место и там уже из него получаешь нужный сервис
Сергей
в симфе можно список сервисов в провайдера добавить в services.yaml через теги
Иван
Юра
Сервис фабрика, который зависит от RequestStack, и выдаёт нужный тип сервиса в зависимости от параметра, по-моему все явно
Юра
А от реквеста зависят не только контроллеры
Юра
Например тот же profiler который собирает данные риквеста
Konstantin
если, допустим, нужно будет воспроизвести этот функционал в консольной команде, тесте или где-то еще, это доставит очень много боли, тк внутренний (сервисный) слой знает о внешнем (слой доступа - хттп)
Konstantin
это протечка абстракции, лучше ее избегать
Konstantin
лично я предпочитаю сделать массив handlers в сервисе-контейнере, у каждого из хендлеров есть метод supports. в цикле перебираете все хендлеры, скормив на вход ваш хттп-реквест, какой хендлер принял этот запрос - такой и обработал
Konstantin
и контейнер чистый от лишних завимостей от хттп, и srp удоволетворен, и гибкости море
Konstantin
если нужен пример кода, чуть позже могу накидать иллюстрацию этого подхода
Иван
Nikolay
Konstantin
это не про доку, а про clean code, скорее. но ваще это и внутри симфони активно используется (см. метод supports в коде компонентов)
Сергей
Konstantin
Vite4eg
Всем привет. Мне надо сформировать сложный Excel. Выдали пример файла. Там куча всяких данных, и есть блок со списком товаров.
Создавать Excel я умею. А есть какие-нибудь подходы по шаблонизации этого?
Взять например готовый Excel, разметить отдельные ячейки как место для подстановок.
Делал кто? есть пример как это реализовать по красоте?
Anton
Konstantin
Konstantin
<?php
// controller
public function fooAction(BarService $barService, Request $request): Response
{
return new JsonResponse($barService->handle($response))
}
class BarService {
/** @param FooHandlerInterface[] */
public function __construct(private readonly array $handlers)
{
}
public function handle(Request $request): array
{
foreach ($this->handlers as $handler) {
if ($handler->supports($request)) {
return $handler->handle($request);
}
}
}
}
interface FooHandlerInterface {
public function supports(Request $request): bool;
public function handle(Request $request): array;
}
class FooHandlerImpl1 implements FooHandlerInterface
{
public function supports(Request $request): bool
{
return $request->query->has('foobar');
}
public function handle(Request $request): array
{
return [
'foo' => 'bar',
];
}
}
Konstantin
добавить по вкусу проверок-исключений-логики
Dmitriy
Так http реквест же у вас протек в сервис FooHandlerImpl1
Konstantin
так ради бога, передавайте не реквест, а ParameterBag
Dmitriy
уж лучше dto
Konstantin
или вообще массив. это как раз нормально, тут реквест - это просто контейнер данных. плохо когда сервис зависит от текущего реквеста в текущем контексте
Konstantin
уж лучше dto
нет разницы, вы в этом хендлере можете проверять что угодно - куки, заголовки, урл-параметры, тело запроса. даже если это и описать всё в дто, получится примерная копия Request, это как раз не особо умно
Konstantin
с реквестом из httpfoundation одна проблема - не совсем удобно в тестах мокать, но и то большой проблемой не является
Dmitriy
Konstantin
ну вы читаете той же жопой, которой и я, похоже. я русским языком, раза два, написал "зависимость сервиса от хттп". это значит, что проинициализировать сервис в контейнере в зависимости от состояния хттп-запроса - это ересь
Konstantin
это никак не связано с тем, что в сервисе у меня будет use Symfony\Component\HttpFoundation\Request
Konstantin
это не та зависимость, речь именно о service arguments, я не знаю как еще понятнее это объяснить
Dmitriy
как пишете так и читаем )
Konstantin
ну вот нет уж)
Юра
Может можно сразу в фабрику передать нужный параметр? Вроде же можно выражения инжектить
Юра
Тогда не надо зависеть от риквеста, только от строки
Юра
Konstantin
а значение запроса откуда взять? expr lang-ом вытащить из @request_stack.mainRequest.query.get('foo')?
Konstantin
это как раз антипаттерн - состояние контейнера недетерминированно, грубо говоря, у нас каждый запрос свой контейнер
Юра
Контейнер один, тоо который скомпилироался
Konstantin
нет
Konstantin
если он зависит от параметра запроса, ты не можешь сказать в данный конкретный момент, во что отрезолвится сервис @foo
Юра
А зачем это тебе
Konstantin
мне? мне - незачем, исходный вопрос был как сделать так, чтобы "если в запросе foo == bar, то достать один сервис, иначе - другой"
Иван
вопрос, что это за роуты такие, что на одном роуте разные хендлеры
Иван
может это разные роуты?
Konstantin
да всякое бывает. у меня вот, например, есть проект. где несколько разных заказов - разные таблицы на разные группы товаров
Юра
Или например когда тебе надо в зависимости от домена подсунуть БД
Юра
Да полно примеров