Symfony 4 服务不同环境下的本地绑定

Ira*_*kli 5 symfony symfony4

我必须在不同的环境中将参数绑定为不同的值,并且遇到了问题。

我正在尝试这个:

# config/services.yaml
services:
    _defaults:
        bind:
            $param: 'param for PROD'

# config/services_dev.yaml
services:
    _defaults:
        bind:
            $param: 'param for DEV'

# src/Controller/SomeController.php
class MyController extends AbstractController
{
    public function example($param)
    {
        echo $param;
    }
}
Run Code Online (Sandbox Code Playgroud)

但它迫使我在services.yamlservices_dev.yaml文件中定义所有服务,否则它不起作用。

我希望为任何环境共享一个services.yaml,并且仅覆盖自定义服务/绑定等,而不是有两个相同的文件,其中列出了用于更改一个绑定值的所有服务。


真正的问题是我必须创建两个具有相同接口的http客户端(真实的和虚拟的),在生产中加载真实的客户端,在开发中加载虚拟的,Symfony 4-s自动装配允许我将接口注入控制器中并选择在绑定中使用哪个客户端:

# config/services.yaml
services:
    _defaults:
        bind:
            'ClientInterface': '@real_client'
    # More services here...

# config/services_dev.yaml
services:
    _defaults:
        bind:
            'ClientInterface': '@dummy_client'
    # Here I don't want to have another copy of the services, 
    # but it does not work without them

# Controller
public function someMethod(ClientInterface $client)
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

在 Symfony 2 中,我能够扩展 services.yml 并在 services_dev.yml 中仅定义我想要覆盖/添加的特定值,但在 Symfony 4 services_dev.yaml中无法使用services.yaml中的服务,我必须保留我的服务在两个不同的文件中相同,这是痛苦的。

有什么建议吗?

谢谢。


我用一个真实的例子再次更新帖子:

服务.yaml

# This file is the entry point to configure your own services.
# Files in the packages/ subdirectory configure your dependencies.

# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
    locale: 'en'
    app.access_token: '%env(string:APP_ACCESS_TOKEN)%'
    app.aws_version: '%env(string:AWS_VERSION)%'
    app.aws_profile: '%env(string:AWS_PROFILE)%'
    app.aws_region: '%env(string:AWS_REGION)%'
    app.aws_queue_url_creation: '%env(string:AWS_QUEUE_URL_CAMPAIGN_CREATION)%'
    app.aws_queue_url_edition: '%env(string:AWS_QUEUE_URL_CAMPAIGN_EDITION)%'
    app.redis_host: '%env(string:REDIS_HOST)%'
    app.redis_port: '%env(string:REDIS_PORT)%'

services:
    # default configuration for services in *this* file
    _defaults:
        autowire: true      # Automatically injects dependencies in your services.
        autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
        public: false       # Allows optimizing the container by removing unused services; this also means
                            # fetching services directly from the container via $container->get() won't work.
                            # The best practice is to be explicit about your dependencies anyway.
        bind:
            App\Service\MessageSenderServiceInterface: '@App\Service\MessageSenderSqsService'

    # makes classes in src/ available to be used as services
    # this creates a service per class whose id is the fully-qualified class name
    App\:
        resource: '../src/*'
        exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'

    # controllers are imported separately to make sure services can be injected
    # as action arguments even if you don't extend any base controller class
    App\Controller\:
        resource: '../src/Controller'
        tags: ['controller.service_arguments']

    # add more service definitions when explicit configuration is needed
    # please note that last definitions always *replace* previous ones

    # Authenticators
    App\Security\ApiKeyAuthenticator:
        arguments:
            - "%app.access_token%"

    # Clients
    App\Client\AwsSqsClient:
        arguments:
            - "%app.aws_version%"
            - "%app.aws_profile%"
            - "%app.aws_region%"

    App\Client\RedisClient:
        arguments:
            - "%app.redis_host%"
            - "%app.redis_port%"

    # Services
    App\Service\MessageSenderSqsService:
        arguments:
            - '@App\Client\AwsSqsClient'
            - '@App\Client\RedisClient'
            - "%app.aws_queue_url_creation%"
            - "%app.aws_queue_url_edition%"

    App\Service\MessageSenderRedisService:
        arguments:
            - '@App\Client\RedisClient'
Run Code Online (Sandbox Code Playgroud)

services_dev.yaml

imports:
    - { resource: services.yaml }

services:
    # default configuration for services in *this* file
    _defaults:
        autowire: true      # Automatically injects dependencies in your services.
        autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
        public: false       # Allows optimizing the container by removing unused services; this also means
                            # fetching services directly from the container via $container->get() won't work.
                            # The best practice is to be explicit about your dependencies anyway.
        bind:
            App\Service\MessageSenderServiceInterface: '@App\Service\MessageSenderRedisService'
Run Code Online (Sandbox Code Playgroud)

控制器.php

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

class TestController extends AbstractController
{
    /**
     * @Route("/api/dummy")
     */
    public function dummyEndpoint(MessageSenderServiceInterface $messageSender)
    {
        echo get_class($messageSender); exit;
    }
}
Run Code Online (Sandbox Code Playgroud)

来自两个环境(产品和开发)的控制器的回显是

App\Service\MessageSenderSqsService
Run Code Online (Sandbox Code Playgroud)

但是,如果我将整个节点“服务”从 services.yaml 复制到 services_dev.yaml 并仅更改绑定配置,则它可以正常工作并表示注入的类是:

App\Service\MessageSenderRedisService
Run Code Online (Sandbox Code Playgroud)

我刚刚注意到,如果我不触摸“_defaults”节点,它会按预期工作,只有当我想覆盖服务的 _defaults 节点时,问题才会开始......

Łuk*_*bek 1

parameters您可以在部分中定义参数config.yml并在 中覆盖此参数config_dev.yml

# config.yml
imports:
    # ...
parameters:
    parameter_1: value 1
    parameter_2: value 2
    # ...
framework:
    # ...

# config_dev.yml
imports:
    # ...
parameters:
    parameter_1: dev value 1
    # ...
framework:
    # ...
Run Code Online (Sandbox Code Playgroud)

该参数可用于service.yml

# service.yml
services:
    _defaults:
        bind:
            $param: '%parameter_1%'
Run Code Online (Sandbox Code Playgroud)