覆盖从 Slim 4 中的路由组注入 class?
Overriding injected class from routing group in Slim 4?
我有一个 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 收到一个 Interface
class MyMiddleware
{
public function __construct(IMyInterface $myServiceImplementingInterface) { /*blah blah*/ }
}
当我们设置容器时,我们告诉它要注入哪个 class 所以 PHP-DI 知道要用哪个 class 构造中间件:
/* 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();
},
];
我建议为不同的组使用 MyMiddleware
class 的两个不同对象,每个对象都使用 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();
我有一个 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 收到一个 Interface
class MyMiddleware
{
public function __construct(IMyInterface $myServiceImplementingInterface) { /*blah blah*/ }
}
当我们设置容器时,我们告诉它要注入哪个 class 所以 PHP-DI 知道要用哪个 class 构造中间件:
/* 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();
},
];
我建议为不同的组使用 MyMiddleware
class 的两个不同对象,每个对象都使用 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();