Symfony 5 从控制台命令生成 URL

我是 Symfony 的新手,正在使用 5.x。我已经使用 Symfony\Component\Console\Command\Command 创建了一个控制台命令,并且正在尝试使用 Symfony\Component\HttpClient\HttpClient 来 POST 到一个 URL。我需要生成在同一台机器上运行的路由的 URL(但将来这可能会更改为不同的机器),因此主机可能类似于 localhost 或 example.com,并且 API 的端口是自定义的。我在网上搜索过,但我得到的唯一可能的解决方案是使用 Symfony\Component\Routing\Generator\UrlGeneratorInterface,并且网上充斥着旧版本 Symfony 的代码示例,我还没有设法得到这个工作。


我最近的尝试是:


public function __construct(UrlGeneratorInterface $router)

{

    parent::__construct();

    $this->router = $router;

}

但我真的不明白如何将参数 UrlGeneratorInterface $router 注入构造函数。我收到未提供参数的错误。我是否必须在其他地方创建 UrlGenerator 的实例并将其注入此处,或者是否有更简单的方法从命令中生成 Symfony 中的绝对 URL?我还不太了解容器。


$url = $context->generate('view', ['Param' => $message['Param']], UrlGeneratorInterface::ABSOLUTE_URL);

服务.yaml:


App\Command\MyCommand:

    arguments: ['@router.default']

  1. 是否有更简单的方法通过显式指定主机、协议、端口、路由、参数等从控制台命令生成 URL?

  2. 为什么 UrlGeneratorInterface 或 RouterInterface 不自动装配?

  3. 如果我还启用了自动装配,是否需要在 services.yaml 中手动指定接线为 $router.default ?

  4. 我知道执行函数的实现可能不正确,但如果不先让构造函数工作,我就无法修复它。这仍在进行中。


江户川乱折腾
浏览 166回答 3
3回答

慕田峪4524236

private $router您似乎遇到的问题不是由于您的服务声明,而是您缺少中变量的声明MyCommand。因此,您可以保留services.yaml要点中显示的内容,无需更改自动装配变量,也不必手动声明命令此外,您不需要$context从路由器中获取,您也可以在您的 中设置基本 URLframework.yaml,在这里您可以找到我找到它的位置。请注意,我从执行中删除了一些代码,这是因为我无法访问您的其他文件。你可以重新添加这个。

慕斯709654

好吧,解决这个问题并不是那么简单。许多文档已过时或未完全解决此问题。这是我到目前为止得到的:服务.yaml:Symfony\Component\Routing\RouterInterface:    arguments: ['@router']应用程序.php:#!/usr/bin/env php<?php// application.phprequire __DIR__.'/vendor/autoload.php';require __DIR__.'/src/Kernel.php';use Symfony\Bundle\FrameworkBundle\Console\Application;use Symfony\Component\Routing\RouterInterface;use Symfony\Component\Dotenv\Dotenv;$dotenv = new Dotenv();$dotenv->load(__DIR__.'/.env', __DIR__.'/.env.local');$kernel = new App\Kernel(getenv('APP_ENV'), getenv('APP_DEBUG'));$kernel->boot();$container = $kernel->getContainer();$application = new Application($kernel);$application->add(new App\Command\MyCommand($container->get('router')));$application->run();注意:我将应用程序导入更改为 Symfony\Bundle\FrameworkBundle\Console\Application我的命令.php:<?php// src/Command/MyCommand.phpnamespace App\Command;use Symfony\Component\Console\Command\Command;use Symfony\Component\Console\Command\LockableTrait;use Symfony\Component\Console\Input\InputInterface;use Symfony\Component\Console\Output\OutputInterface;use Symfony\Component\Routing\Generator\UrlGeneratorInterface;use Symfony\Component\Routing\RouterInterface;use Symfony\Component\HttpClient\HttpClient;use App\SQSHelper;class MyCommand extends Command{    use LockableTrait;    // the name of the command (the part after "bin/console")    protected static $defaultName = 'app:my-command';    protected $router;    public function __construct(RouterInterface $router)    {        parent::__construct();        $this->router = $router;    }    protected function configure()    {    }    protected function execute(InputInterface $input, OutputInterface $output)    {        if($this->lock()) { // Prevent running more than one instance            $endpoint =             $queueName = 'Queue';            $queue = new SQSHelper();            while($queue->getApproxNumberOfMessages($queueName)) {                $message = $queue->receiveMessage($queueName);                if($message) {                    if($message['__EOQ__'] ?? FALSE) // End-of-Queue marker received                        break;                    $context = $this->router->getContext();                    $context->setHost('localhost');                    $context->setHttpPort('49100');                    $context->setHttpsPort('49100');                    $context->setScheme('https');                    $context->setBaseUrl('');                    $url = $this->router->generate('ep', ['MessageId' => $message['MessageId']], UrlGeneratorInterface::ABSOLUTE_URL);                    $client = HttpClient::create();                    $response = $client->request('POST', $url, [                        'headers' => ['Content-Type' => 'application/json'],                        'body' => $message['Body'] // Already JSON encoded                    ]);                }            }            $this->release(); // Release lock            // this method must return an integer number with the "exit status code"            // of the command. You can also use these constants to make code more readable            // return this if there was no problem running the command            // (it's equivalent to returning int(0))            return Command::SUCCESS;            // or return this if some error happened during the execution            // (it's equivalent to returning int(1))            // return Command::FAILURE;        }    }}如果有什么感觉不对,或者如果您可以提供更好的解决方案或改进,请贡献...

忽然笑

Symfony 5.1 引入的解决方案:https://symfony.com/doc/current/routing.html#generating-urls-in-commands在命令中生成 URL 与在服务中生成 URL 的工作方式相同。唯一的区别是命令不在 HTTP 上下文中执行。因此,如果您生成绝对 URL,您将获得 http://localhost/ 作为主机名,而不是您的真实主机名。解决方案是配置 default_uri 选项来定义命令在生成 URL 时使用的“请求上下文”:# config/packages/routing.yamlframework:&nbsp; &nbsp; router:&nbsp; &nbsp; &nbsp; &nbsp; # ...&nbsp; &nbsp; &nbsp; &nbsp; default_uri: 'https://example.org/my/path/'
打开App,查看更多内容
随时随地看视频慕课网APP