Переопределить введенный класс из группы маршрутизации в Slim 4? - PullRequest
0 голосов
/ 01 мая 2020

У меня есть приложение Slim4, состоящее из нескольких модулей, разделенных на разные группы маршрутизации, например:

$app->group('/app', function(RouteCollectorProxy  $app) {
   /*blah blah*/
})->add(MyMiddleWare::class);

$app->group('/api', function(RouteCollectorProxy  $app) {
   /*blah blah*/
})->add(MyMiddleware::class);

$app->group('/admin', function(RouteCollectorProxy  $app) {
   /*blah blah*/
})->add(MyMiddleware::class);

MyMiddleware получает интерфейс

class MyMiddleware
{
    public function __construct(IMyInterface $myServiceImplementingInterface) { /*blah blah*/ }
}

Когда мы устанавливаем контейнер, мы говорим ему, какой класс внедрить, чтобы PHP -D я знал, какой класс для создания промежуточного программного обеспечения:

/* bootstraping */
$containerBuilder = new ContainerBuilder();
$containerBuilder->addDefinitions(__DIR__ . '/container.php');
$container = $containerBuilder->build();

и

/*container.php*/
return [
    IMyInterface::class => function (ContainerInterface $container) {
        return new MyServiceImplementingInterface();
    },
];

My Главный вопрос:

Можно ли как-то отменить реализацию настройки контейнера для IMyInterface::class на основе группы маршрутизации? поэтому у меня может быть что-то вроде:

Настройка основного контейнера:

/*container.php*/
return [
    IMyInterface::class => function (ContainerInterface $container) {
        return new MyServiceImplementingInterface();
    },
];

Specifi c Настройка контейнера группы маршрутов:

/*container.admin.php*/
return [
    IMyInterface::class => function (ContainerInterface $container) {
        return new AnotherServiceImplementingInterface();
    },
];

1 Ответ

1 голос
/ 01 мая 2020

Я предлагаю использовать два разных объекта класса MyMiddleware для разных групп, каждый из которых построен с использованием соответствующей реализации IMyInterface. Вы можете указать PHP -DI вызвать конструктор с нужными параметрами.

Здесь я создал два экземпляра MyMiddleware, один с именем AdminMiddleware, а другой с именем ApiMiddleware в контейнер. используя метод DI\create()->constructor(), я настраиваю DI для внедрения различных реализаций IMyInterface при построении этих двух объектов:

<?php

use DI\ContainerBuilder;
use Slim\Factory\AppFactory;

// this is the path of autoload.php relative to my index.php file
// change it according to your directory structure
require __DIR__ . '/../vendor/autoload.php';

interface IMyInterface {
    public function sampleMethod();
}

class MyServiceImplementingInterface implements IMyInterface {
    public function sampleMethod() {
        return 'This implementation is supposed to be used for API endpoint middleware';
    }
}

class AnotherServiceImplementingInterface implements IMyInterface {
    public function sampleMethod() {
        return 'This implementation is supposed to be used for Admin middleware';
    }
}

class MyMiddleware
{
    private $service;
    public function __construct(IMyInterface $myServiceImplementingInterface) { 
        $this->service = $myServiceImplementingInterface;
    }
    public function __invoke($request, $handler)
    {
        $response = $handler->handle($request);
        $response->getBody()->write($this->service->sampleMethod());
        return $response;
    }
}

$containerBuilder = new ContainerBuilder();
$containerBuilder->addDefinitions([
    'AdminMiddleware' => DI\create(MyMiddleware::class)->constructor(DI\get(AnotherServiceImplementingInterface::class)),
    'ApiMiddleware' => DI\create(MyMiddleware::class)->constructor(DI\get(MyServiceImplementingInterface::class))
]);

$container = $containerBuilder->build();

AppFactory::setContainer($container);
$app = AppFactory::create();

$app->group('/admin', function($app) {
    $app->get('/dashboard', function($request, $response, $args){
        return $response;
    });
})->add($container->get('AdminMiddleware'));
$app->group('/api', function($app) {
    $app->get('/endpoint', function($request, $response, $args){
        return $response;
    });
})->add($container->get('ApiMiddleware'));

$app->run();
...