从Slim 4中的路由组覆盖注入的类?

问题描述 投票:0回答:1

我有一个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-DI知道使用哪个类来构造中间件:

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

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

我的主要问题是:

是否有可能基于路由组覆盖IMyInterface::class的容器设置的实现?这样我就可以像:

主容器设置:

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

特定路线组容器设置:

/*container.admin.php*/
return [
    IMyInterface::class => function (ContainerInterface $container) {
        return new AnotherServiceImplementingInterface();
    },
];
php slim php-di slim-4
1个回答
1
投票

我建议对不同的组使用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();
© www.soinside.com 2019 - 2024. All rights reserved.