За последние 24 часа нас посетили 38913 программистов и 8160 роботов. Сейчас ищут 1608 программистов ...

Доступ к контейнеру где-то

Тема в разделе "PHP для новичков", создана пользователем Вероломство, 1 авг 2023.

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

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

    С нами с:
    19 июн 2017
    Сообщения:
    626
    Симпатии:
    24
    говнокодю некоторый код

    сервис

    PHP:
    1. class Debugger
    2. {
    3.     private $display;
    4.     private $handler;
    5.  
    6.     public function __construct($display, $handler)
    7.     {
    8.         $this->display = $display;
    9.         $this->handler = $handler;
    10.     }
    11.  
    12.     public function __invoke(Request $request, Response $response)
    13.     {
    14.         set_error_handler(function ($code, $text, $file, $line) {
    15.             throw new ErrorException($text, 0, $code, $file, $line);
    16.         });
    17.  
    18.         set_exception_handler(function (Throwable $throwable) use ($request, $response) {
    19.             call_user_func(
    20.                 new $this->handler, // не будет автовайринга, нужно сделать - container->get($this->handler)
    21.                 $request,
    22.                 $response,
    23.                 [
    24.                     'code' => $throwable->getCode(),
    25.                     'text' => $throwable->getMessage(),
    26.                     'file' => $throwable->getFile(),
    27.                     'line' => $throwable->getLine(),
    28.                 ]
    29.             );
    30.         });
    31.     }
    32. }
    провайдер

    PHP:
    1. class DebuggerProvider extends Provider
    2. {
    3.     public function register()
    4.     {
    5.         $this->app->container->set(Debugger::class, function () {
    6.             $debugger = $this->app->container->get('debugger');
    7.  
    8.             return new Debugger(
    9.                 $debugger['display'],
    10.                 $debugger['handler'] // строка 'DebuggerAction::class'
    11.             );
    12.         });
    13.     }
    14.  
    15.     public function boot(Request $request, Response $response)
    16.     {
    17.         call_user_func(
    18.             $this->app->container->get(Debugger::class),
    19.             $request,
    20.             $response
    21.         );
    22.     }
    23. }
    экшен

    PHP:
    1. class DebuggerAction extends Action
    2. {
    3.     private $view;
    4.  
    5.     public function __construct(View $view) // не будет работать если экшен не вызван из контейнера
    6.     {
    7.         $this->view = $view; // хотелось бы так
    8.         // $this->view = new View(); // не ну можно и так сделать
    9.     }
    10.  
    11.     public function __invoke(Request $request, Response $response, $args)
    12.     {
    13.         var_dump($args);
    14.  
    15.         $response->statusCode(404); // или $response->statusCode($args['code']);
    16.     }
    17. }
    как мне в сервисе стартануть $this->handler из контейнера, чтобы работал автовайринг?

    есть мысль такая

    PHP:
    1. class DebuggerProvider extends Provider
    2. {
    3.     public function register()
    4.     {
    5.         $this->app->container->set(Debugger::class, function () {
    6.             $debugger = $this->app->container->get('debugger');
    7.  
    8.             return new Debugger(
    9.                 $debugger['display'],
    10.                 $this->app->container->get($debugger['handler']) // создали экземпляр, поместив его в контейнер
    11.             );
    12.         });
    13.     }
    14.  
    15.     public function boot(Request $request, Response $response)
    16.     {
    17.         call_user_func(
    18.             $this->app->container->get(Debugger::class),
    19.             $request,
    20.             $response
    21.         );
    22.     }
    23. }
    24.  
    25. class Debugger
    26. {
    27.     private $display;
    28.     private $handler;
    29.  
    30.     public function __construct($display, $handler)
    31.     {
    32.         $this->display = $display;
    33.         $this->handler = $handler; // тут уже экземпляр экшена из контейнера, в нём будет работать автовайринг
    34.     }
    35.  
    36.     public function __invoke(Request $request, Response $response)
    37.     {
    38.         set_error_handler(function ($code, $text, $file, $line) {
    39.             throw new ErrorException($text, 0, $code, $file, $line);
    40.         });
    41.  
    42.         set_exception_handler(function (Throwable $throwable) use ($request, $response) {
    43.             call_user_func(
    44.                 $this->handler, // вызвали экземпляр экшена, new не нужно делать, отработает магия
    45.                 $request,
    46.                 $response,
    47.                 [
    48.                     'code' => $throwable->getCode(),
    49.                     'text' => $throwable->getMessage(),
    50.                     'file' => $throwable->getFile(),
    51.                     'line' => $throwable->getLine(),
    52.                 ]
    53.             );
    54.         });
    55.     }
    56. }
    57.  
    58. class DebuggerAction extends Action
    59. {
    60.     private $view;
    61.  
    62.     public function __construct(View $view) // будет работать - экшен вызван из контейнера
    63.     {
    64.         $this->view = $view;
    65.     }
    66.  
    67.     public function __invoke(Request $request, Response $response, $args)
    68.     {
    69.         var_dump($args);
    70.  
    71.         $response->statusCode(404); // или $response->statusCode($args['code']);
    72.     }
    73. }
    Но что мне не нравится, если в провайдере собирать сервис, передавая в конструктор экземпляр экшена - это то, что если ошибки нет в приложухе, то в контейнере постоянно висит как бы лишний экземпляр этого экшена, это нормально?

    p.s. если я прокину резольвер (не понимаю сути резольвера, он использует контейнер, так не проще ли использовать везде контейнер, позволив контейнеру автовайрить самого себя) в сервис с параметрами вместе при сборке, то нарушится как бы общая логика сервиса - если его взять отдельно, то тогда нужно чтобы и там был резольвер))) поэтому сервис собирается без передачи в конструктор - резольвера (фактически контейнера)
     
    #1 Вероломство, 1 авг 2023
    Последнее редактирование: 1 авг 2023