如何在Symfony2控制器中从parameters.yml文件读取数据?

156

我已经在我的app/config/parameters.yml文件中设置了几个自定义变量。

parameters:
    api_pass: apipass
    api_user: apiuser

我需要从我的控制器中访问它们,已经尝试使用以下代码获取:

$this->get('api_user');

当我试图在控制器文件中使用这个时,我收到了以下错误信息:

You have requested a non-existent service "api_user".

如何正确地进行这个操作?

8个回答

304
在Symfony 2.6及更早版本中,要在控制器中获取参数 - 首先应该获取容器,然后获取所需的参数。
$this->container->getParameter('api_user');

这个文档章节 来进行解释。

在控制器中使用$this->get() 方法可以加载一个服务 (文档)

Symfony 2.7和更新版本 中,您可以使用以下代码在控制器中获取参数:

$this->getParameter('api_user');

3
注意控制器中的get方法也使用容器,但它只能从容器中获取服务,而不能获取参数。您需要使用getParameter来获取参数。 - Wouter J
当我尝试使用$this->getContainer()->getParameter('api_user');时,我会得到致命错误:调用未定义的方法..Longpath..\Controller::getContainer()。 - Bohr
1
@Bohr 抱歉,Symfony2 的版本不同。我已经编辑了我的回答 - 现在请检查一下 ;) - Vitalii Zurian
2
文档的URL现在是http://symfony.com/doc/2.7/components/dependency_injection/parameters.html。 - SilvioQ
Symfony 2.7 及更新版本:$this->hasParameter() 目前尚未工作。 - Saman Mohamadi
您现在可以使用Rector立即升级:https://github.com/rectorphp/rector/pull/333 - Tomas Votruba

32

清洁的方式-2018+, Symfony 3.4+

从2017年和Symfony 3.3 + 3.4开始,有了更加清晰的方式-易于设置和使用。

与其使用容器和服务/参数定位器反模式,您可以通过将参数传递给类的构造函数来实现。不用担心,这不是费时的工作,而是一个设置一次并忘记的方法。

如何在2个步骤中设置它?

1. app/config/services.yml

# config.yml

# config.yml
parameters:
    api_pass: 'secret_password'
    api_user: 'my_name'

services:
    _defaults:
        autowire: true
        bind:
            $apiPass: '%api_pass%'
            $apiUser: '%api_user%'

    App\:
        resource: ..

2. 任何Controller

<?php declare(strict_types=1);

final class ApiController extends SymfonyController
{
    /**
     * @var string 
     */
    private $apiPass;

    /**
     * @var string
     */
    private $apiUser;

    public function __construct(string $apiPass, string $apiUser)
    {
        $this->apiPass = $apiPass;
        $this->apiUser = $apiUser;
    }

    public function registerAction(): void
    {
        var_dump($this->apiPass); // "secret_password"
        var_dump($this->apiUser); // "my_name"
    }
}

即时升级就绪!

如果您使用较旧的方法,您可以使用Rector进行自动化 升级

阅读更多

这被称为构造函数注入覆盖服务定位器方法。

要了解更多信息,请查看我的文章如何以简洁的方式在Symfony控制器中获取参数。(它已经过测试,并针对新的Symfony主要版本(5、6...)进行更新。)


这个主题的新极简方法:https://www.tomasvotruba.cz/blog/2018/11/05/do-you-autowire-services-in-symfony-you-can-autowire-parameters-too/ - Tomas Votruba

12
在Symfony 4中,您可以使用 ParameterBagInterface :
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;

class MessageGenerator
{
    private $params;

    public function __construct(ParameterBagInterface $params)
    {
        $this->params = $params;
    }

    public function someMethod()
    {
        $parameterValue = $this->params->get('parameter_name');
        // ...
    }
}

并在 app/config/services.yaml 中:

parameters:
    locale: 'en'
    dir: '%kernel.project_dir%'

它在控制器和表单类中对我都有效。 有关详细信息,请参阅Symfony博客


1
传递整个参数包就像传递整个容器。这只有在“某些特定服务需要大量容器参数”的情况下才有意义(引用自该帖子)。 - Tomas Votruba
那么,您的意思是传递整个参数会影响性能吗? - Ghazaleh Javaheri
这是其中一个原因,但主要是为了可读性。如果我看到参数名 $meetupApiKey,我比在 $parameterBag 中更清楚地知道可以期望什么。 - Tomas Votruba

12

我会尝试为您进行翻译:

parameters.yml

我用swiftmailer给您发了一个示例:

recipients: [email1, email2, email3]

服务:

your_service_name:
        class: your_namespace
        arguments: ["%recipients%"]

服务的种类:

protected $recipients;

public function __construct($recipients)
{
    $this->recipients = $recipients;
}

2

2

1
在Symfony 4.3.1中,我使用以下代码:

services.yaml

HTTP_USERNAME: 'admin'
HTTP_PASSWORD: 'password123'

FrontController.php

$username = $this->container->getParameter('HTTP_USERNAME');
$password = $this->container->getParameter('HTTP_PASSWORD');

在4.8版本中无法工作。你确定它曾经能够工作吗? - Ricardo Martins
1
我真的忘了这件事,但是很可能它有效,因为我只发布经过测试的东西! - Achraf JEDAY
2
抱歉,Acharaf。我不知道,但在我的控制器中不起作用。 在您的控制器内部,您可以直接调用 getParameter,无需 DI。即:$this->getParameter('foo')。这就是我在 SF 4.8 中使其工作的方法。 - Ricardo Martins

-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接