如何从早期/自动加载的 Symfony 3 路由器生成绝对 URL [英] How to generate Absolute URL from Early/Auto loaded Symfony 3 router

查看:15
本文介绍了如何从早期/自动加载的 Symfony 3 路由器生成绝对 URL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写 Guards 来处理我的 Symfony 3 应用程序的 OAuth.

I am writing Guards to handle OAuth for my Symfony 3 application.

作为其中的一部分,在我的一项服务中,我需要生成一个绝对 URL 作为回调 URL 发送到 Twitter.

As part of it, in one of my services, I need to generate an absolute URL to send to Twitter as the Callback URL.

#services.yml
...
app.twitter_client:
    class: MyApiBundleServicesTwitterClient
    arguments:
        - %twitter_client_id%
        - %twitter_client_secret%
        - connect_twitter_check
        - '@request_stack'
        - '@router'
        - '@logger'
app.twitter_authenticator:
    class: MyApiBundleSecurityTwitterAuthenticator
    arguments:
        - '@app.twitter_client'
        - '@logger'

记录器是临时用于调试.

The logger is temporary for debugging.

#TwitterClient.php service
...
use MonologLogger;
use SymfonyComponentHttpFoundationRedirectResponse;
use SymfonyComponentHttpFoundationRequestStack;
use SymfonyComponentRoutingRouterInterface;
class TwitterClient
{

/**
 * TwitterClient constructor.
 * @param string          $identifier
 * @param string          $secret
 * @param string          $callbackUrl
 * @param RequestStack    $requestStack
 * @param RouterInterface $router
 * @param Logger          $logger
 */
public function __construct(
    string $identifier,
    string $secret,
    string $callbackUrl,
    RequestStack $requestStack,
    RouterInterface $router,
    Logger $logger
) {
    $callbackUrl = $router->generate($callbackUrl, [], RouterInterface::ABSOLUTE_URL);
    $logger->info($callbackUrl);
    ...
}

当它输出 $callbackUrl 到日志时,它只是说 localhost,即使我使用不同的 URL 访问它.

And when it outputs the $callbackUrl to the logs, it just says localhost, even though I am accessing it using a different URL.

http://localhost/connect/twitter/check

但是如果我从我的控制器上做同样的事情,它会输出完整的正确 URL.

But if I do the same from my a controller, it outputs the full proper URL.

#TwitterController.php
...
use SymfonyComponentRoutingAnnotationRoute;
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentHttpFoundationRedirectResponse;
use SymfonyComponentRoutingRouterInterface;


class TwitterController extends Controller
{
    /**
     * @Route("/connect/twitter")
     * @return RedirectResponse
     */
    public function connectAction()
    {
        /** @var RouterInterface $router */
        $router = $this->container->get('router');
        $callbackUrl = $router->generate('connect_twitter_check', [], RouterInterface::ABSOLUTE_URL);
        /** @var Logger $logger */
        $logger = $this->container->get('logger');
        $this->container->get('logger')
            ->info($callbackUrl);
        ...

输出:

https://dev.myapi.com:8082/app_dev.php/connect/twitter/check

dev.myapi.com 域在我的主机文件中设置并指向 localhost,以便更容易区分我的本地应用程序,也更容易与 OAuth 服务集成.

The dev.myapi.com domain is set up in my hosts file and points to localhost, to make it easier to differentiate between my local apps and also to make it easier to integrate with OAuth services.

推荐答案

我通过设置路由器上下文设法解决了这个问题.我已经在 RequestStack 中加载以访问用户的 IP,因此我使用它来设置 Route 的上下文,然后路由器按预期工作.我在尝试在构造函数中使用 RequestStack 时遇到了 问题,所以我最终重构了它,以便它尽可能晚地使用 RequestStack.

I managed to solve this by setting the Router context. I already loaded in the RequestStack to access the user's IP, so I used it to set the context of the Route and then the router worked as expected. I ran into problems trying to use the RequestStack in the constructor, so I ended up refactoring it so that it used the RequestStack as late as possible.

class TwitterClient
{
    private $identifier;
    private $secret;
    private $callbackUrl;
    private $requestStack;
    private $router;
    private $server;

    /**
     * TwitterClient constructor.
     *
     * @param string          $identifier
     * @param string          $secret
     * @param string          $callbackUrl
     * @param RequestStack    $requestStack
     * @param RouterInterface $router
     */
    public function __construct(
        string $identifier,
        string $secret,
        string $callbackUrl,
        RequestStack $requestStack,
        RouterInterface $router
    ) {
        $this->identifier = $identifier;
        $this->secret = $secret;
        $this->callbackUrl = $callbackUrl;
        $this->requestStack = $requestStack;
        $this->router = $router;
    }

    /**
     * Wait until the last moment to create the Twitter object to make sure that the requestStack is loaded.
     *
     * @return LeagueOAuth1ClientServerTwitter
     */
    private function getServer()
    {
        if (!$this->server) {
            $context = new RequestContext();
            $context->fromRequest($this->requestStack->getCurrentRequest());
            $this->router->setContext($context);
            $callbackUrl = $this->router->generate($this->callbackUrl, [], RouterInterface::ABSOLUTE_URL);
            $this->server = new Twitter(
                [
                    'identifier' => $this->identifier,
                    'secret' => $this->secret,
                    'callback_uri' => $callbackUrl,
                ]
            );
        }

        return $this->server;
    }
    ...
}

这篇关于如何从早期/自动加载的 Symfony 3 路由器生成绝对 URL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆