За последние 24 часа нас посетили 17405 программистов и 1599 роботов. Сейчас ищут 1166 программистов ...

Как прописать интерфейс с учётом splat?

Тема в разделе "PHP для профи", создана пользователем Вероломство, 9 ноя 2024.

  1. Вероломство

    Вероломство Активный пользователь

    С нами с:
    19 июн 2017
    Сообщения:
    626
    Симпатии:
    24
    Роут:

    PHP:
    1. return function (App $app) {
    2.  
    3.     $app->get('/{id:\d+}', ExampleAction::class);
    4. };
    Обработчик:

    PHP:
    1. readonly class Handler implements HandlerInterface
    2. {
    3.     public function __construct(
    4.         private ContainerInterface $container,
    5.         private RouteResult        $routeResult
    6.     )
    7.     {
    8.     }
    9.  
    10.     public function handle(Request $request): Response
    11.     {
    12.         return call_user_func(
    13.             $this->container->get($this->routeResult->getAction()),
    14.             $request,
    15.             new Response(),
    16.             ...$this->routeResult->getParameters()
    17.         );
    18.     }
    19. }
    Теперь я хочу, чтобы везде в экшенах каждый раз не писать вручную внедрение Request и Response, написать интерфейс:

    PHP:
    1. interface ActionInterface
    2. {
    3.     public function __invoke(Request $request, Response $response): Response;
    4. }
    В итоге имеем такой вот экшен:

    PHP:
    1. class ExampleAction implements ActionInterface
    2. {
    3.     public function __invoke(Request $request, Response $response, int $id): Response
    4.     {
    5.         var_dump($id);
    6.  
    7.         return $response;
    8.     }
    9. }
    Ошибка: должно соответствовать интерфейсу

    Как помирить экшен с интерфейсом, учитывая splat?

    p.s. я могу не сплатом передать массив в интерфейс, который тупо совпадёт с массивом экшена, но есть желание именно сплатом доставать переменные, без обработки массива в экшене, ну и чтобы его не прописывать, если работы с ним не будет - пустой
     
  2. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.103
    Симпатии:
    1.243
    Адрес:
    там-сям
    @Вероломство ну я чего ты хотел, сигнатура метода другая, чем в ActionInterface! Сделай тогда splat (spread) в самом интерфейсе и его имплементирующих классах. Чтобы было одинаково.

    Вообще это выглядит как грязный хак, ИМХО. Строгость в типах и сигнатурах помогает писать надёжный код, а такие хаки пробивают дыру в строгости.
    --- Добавлено ---
    Еще ты можешь сделать интерфейс вообще без методов, просто имя задать и где-то его вставлять в implements. Зависит от твоих целей.
     
    Вероломство нравится это.
  3. Вероломство

    Вероломство Активный пользователь

    С нами с:
    19 июн 2017
    Сообщения:
    626
    Симпатии:
    24
    @artoodetoo вообще-то да, хак, облегчающий, вылазит вилами, ведь может быть и не __invoke

    кстати если сплатовому параметру задать дефолт, то работает, но мне не нравится дефолт, потому что тогда паттерн решает наличие роута, а он же может быть необязательным

    отказался от интерфейса экшену, повёлся на автокомплит IDE при имплементации, если не будет шторма, то всё одно руками писать

    затупил

    лан порешали, в топку интерфейс запроса и ответа
     
  4. Вероломство

    Вероломство Активный пользователь

    С нами с:
    19 июн 2017
    Сообщения:
    626
    Симпатии:
    24
    @artoodetoo вопрос небольшой по дефолту: а это вообще нормально если так делать, работать работает, но интуитивно посещают сомнения в правильности такого подхода:

    PHP:
    1. interface ActionInterface
    2. {
    3.     public function __invoke(Request $request, Response $response): Response;
    4. }
    5.  
    6. class ExampleAction implements ActionInterface
    7. {
    8.     public function __invoke(Request $request, Response $response, int $id = 0): Response
    9.     {
    10.         var_dump($id);
    11.         return $response;
    12.     }
    13. }
    Имеет такое право на жизнь?
     
  5. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.103
    Симпатии:
    1.243
    Адрес:
    там-сям
    По моему нескромному мнению, так делать нельзя даже если PHP такое пропустит. Я в последнее время топлю за типизацию, соответствие нормам, против костылей. Пользуюсь статическим анализом кода phpstan. Послабления выходят боком. Какие-нибудь газенбаги всплывают или после обновления система раком встает.
    Нормально делай, нормально будет )))
     
    Вероломство нравится это.
  6. Вероломство

    Вероломство Активный пользователь

    С нами с:
    19 июн 2017
    Сообщения:
    626
    Симпатии:
    24