php laravel框架 - 如何从服务访问应用程序参数?




laravel生成repository 5.6教程 (5)

从我的控制器,我访问应用程序参数(在/app/config

$this->container->getParameter('my_param')

但我不知道如何从服务访问它(我想我的服务类不应该扩展Symfony\Bundle\FrameworkBundle\Controller\Controller )。

我应该将所需参数映射到我的服务注册中,如下所示:

#src/Me/MyBundle/Service/my_service/service.yml
parameters:
    my_param1: %my_param1%
    my_param2: %my_param2%
    my_param3: %my_param3%

或类似的东西? 我应该如何从服务访问我的应用程序参数?

这个问题看起来是一样的,但是我的实际答案是它(来自控制器的参数),我说的是从服务访问。


Answers

作为上述一些问题的解决方案,我定义了一个数组参数然后注入它。 稍后添加新参数只需要添加参数数组,而无需对service_container参数或构造进行任何更改。

所以扩展@richsage答案:

parameters.yml

parameters:
    array_param_name:
        param_name_1:   "value"
        param_name_2:   "value"

services.yml

services:
    my_service:
        class:  My\Bundle\Service\MyService
        arguments: [%array_param_name%]

然后在课堂内访问

public function __construct($params)
{
    $this->param1 = array_key_exists('param_name_1',$params)
        ? $params['param_name_1'] : null;
    // ...
}

清洁方式2018年

自2017年和Symfony 3.4以来,有更清洁的方式 - 易于设置和使用。

您可以通过它的构造函数将参数传递给类 ,而不是使用容器和服务/参数定位器反模式。 别担心,这不是时间要求很高的工作,而是设置一次忘记方法。

如何分两步设置?

1. config.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 ...))。


为什么不允许您的服务直接访问容器,而不是逐个映射您需要的参数? 这样做,如果添加了新参数(与您的服务相关),则无需更新映射。

为此:

对服务类进行以下更改

use Symfony\Component\DependencyInjection\ContainerInterface; // <- Add this

class MyServiceClass
{
    private $container; // <- Add this
    public function __construct(ContainerInterface $container) // <- Add this
    {
        $this->container = $container;
    }
    public function doSomething()
    {
        $this->container->getParameter('param_name_1'); // <- Access your param
    }
}

在services.yml中将@service_container添加为“arguments”

services:
  my_service_id:
    class: ...\MyServiceClass
    arguments: ["@service_container"]  // <- Add this

您可以通过在服务定义中指定参数,以与注入其他服务相同的方式将参数传递给服务。 例如,在YAML中:

services:
    my_service:
        class:  My\Bundle\Service\MyService
        arguments: [%my_param1%, %my_param2%]

其中%my_param1% etc对应于名为my_param1的参数。 那么你的服务类构造函数可以是:

public function __construct($myParam1, $myParam2)
{
    // ...
}

不要试图做到这一点,但如果你使用Sublime Text作为编辑器,步骤是:

  1. 选择块
  2. CMD + /在Mac或CTRL + /在Linux和Windows上
  3. 利润

我想像其他编辑也有类似的功能。 你在使用哪一个? 我很乐意做一些挖掘工作。







php symfony yaml