【问题标题】:How to access slim4's routeParser with the PHP-DI setup demonstrated in Slim-Skeleton?如何使用 Slim-Skeleton 中演示的 PHP-DI 设置访问 slim4 的 routeParser?
【发布时间】:2020-04-24 10:43:10
【问题描述】:

我已经基于 SlimPHP 团队的 Slim Skeleton 应用程序设置了一个新应用程序。在我的路由定义中,我希望能够以described in the Slim4 documentation 访问路由解析器。因此,例如,我希望能够像这样编辑骨架的 app/routes.php 文件:

    $app->get('/', function (Request $request, Response $response) {
        $routeParser = $app->getRouteCollector()->getRouteParser();  // this doesn't work
        $response->getBody()->write('Hello world! ' . $routeParser->urlFor('something'));
        return $response;
    });

$app->getRouteCollector()->getRouteParser() 不起作用是有道理的,因为这里没有定义 $app。但我认为我们会改为调用$this->getRouteCollector()->getRouteParser();,但这会产生错误:"Call to undefined method DI\\Container::getRouteCollector()"

看来我的困惑肯定是关于依赖注入,这对我来说是新的,对我来说并不是自然而然的。老实说,我很想在其他地方(在 index.php 中?)定义 $routeParser 变量,这样我就可以在任何路由定义中访问它,而不必每次都调用 $app->getRouteCollector()->getRouteParser()。但目前我会接受任何有效的方法。

【问题讨论】:

  • @Jeto 如果是这样,它会以我无法理解的方式适用于我的情况。另请注意,@odan 和 @Nima 的出色答案不使用 use 或通过引用传递任何内容,所以我认为这不是最好的方法。
  • 公平地说,我不熟悉 Slim 框架,所以我将撤回我的近距离投票,因为我认为它类似于 Silex 等微框架,其中useing @ 987654332@ 很常见(在您的情况下为$app->get('/', function (Request $request, Response $response) use ($app) { ... })。这可能不是 Slim 中推荐的方式,不能肯定地说。

标签: php slim php-di slim-4


【解决方案1】:

Slim 骨架实际上展示了您需要实现的目标的示例。创建App实例in index.php后,有这样的赋值:

// Instantiate the app
AppFactory::setContainer($container);
$app = AppFactory::create();
$callableResolver = $app->getCallableResolver();

你也可以这样做:

$routeParser = $app->getRouteCollector()->getRouteParser();

如果你真的需要这个 RouteParser 实例在每个路由回调中可用,你可以把它放在依赖容器中,比如:

$container->set(Slim\Interfaces\RouteParserInterface::class, $routeParser);

然后您可以使用 PHP-DI 自动装配功能将此 RouteParser 注入到控制器构造函数中:

use Slim\Interfaces\RouteParserInterface;
class SampleController {
    public function __construct(RouteParserInterface $routeParser) {
        $this->routeParser = $routeParser;
        //...
    }
}

或者如果您需要在任何路由回调中调用$container->get()

$app->get('/', function (Request $request, Response $response) {
    $routeParser = $this->get(Slim\Interfaces\RouteParserInterface::class);
    $response->getBody()->write('Hello world! ' . $routeParser->urlFor('something'));
    return $response;
});

【讨论】:

  • 我喜欢这个答案!它不仅解决了我的问题,还帮助我更好地了解整个 DI 是如何工作的。谢谢!
  • 问题:如果我不打算使用自动连接的东西,我似乎可以set 一个简单的变量而不是一个类,就像这样:$container->set('routeParser', $routeParser);。然后我可以在我的路由回调中使用$this->get('routeParser') get。这样做有什么缺点吗?
  • I can set a simple variable rather than a class...您没有设置。在 php 中,MyClass::class 是该类的完全限定名称(即包含其完整命名空间),它是一个字符串。 $container->set() 的第一个参数也应该是一个字符串,是的,你可以使用任何你喜欢的名称(它不必是 routeParser),但在这种情况下你不能使用自动连接和 是缺点。
【解决方案2】:

您不需要 App 实例。您可以使用RouteContext 获取RouteParser:

$routeParser = \Slim\Routing\RouteContext::fromRequest($request)->getRouteParser();

【讨论】:

  • 我喜欢这个答案!我的路线仍然很混乱,但它可以立即在一行中运行,并且肯定回答了我的问题。谢谢!
  • 这需要$app->addRoutingMiddleware(); 才能工作(否则我们会得到Uncaught RuntimeException: Cannot create RouteContext before routing has been completed。)
  • @FabienSnauwaert 正如 Slim 手册中所述,如果您想访问中间件中的路由信息​​,这是正确的。如果您只是在应用程序的操作方法中构建路由,这将起作用 find(因为路由已被处理以到达那里)。
猜你喜欢
  • 1970-01-01
  • 2016-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-25
相关资源
最近更新 更多