How to Manage Common Dependencies with Parent Services

As you add more functionality to your application, you may well start to have related classes that share some of the same dependencies. For example, you may have multiple repository classes which need the doctrine.orm.entity_manager service and an optional logger service:

アプリケーションに機能を追加すると、同じ依存関係の一部を共有する関連クラスが発生する可能性があります。たとえば、doctrine.orm.entity_manager サービスとオプションのロガー サービスを必要とする複数のリポジトリ クラスがあるとします。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// src/Repository/BaseDoctrineRepository.php
namespace App\Repository;

use Doctrine\Persistence\ObjectManager;
use Psr\Log\LoggerInterface;

// ...
abstract class BaseDoctrineRepository
{
    protected $objectManager;
    protected $logger;

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

    public function setLogger(LoggerInterface $logger): void
    {
        $this->logger = $logger;
    }

    // ...
}

Your child service classes may look like this:

子サービス クラスは次のようになります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// src/Repository/DoctrineUserRepository.php
namespace App\Repository;

use App\Repository\BaseDoctrineRepository;

// ...
class DoctrineUserRepository extends BaseDoctrineRepository
{
    // ...
}

// src/Repository/DoctrinePostRepository.php
namespace App\Repository;

use App\Repository\BaseDoctrineRepository;

// ...
class DoctrinePostRepository extends BaseDoctrineRepository
{
    // ...
}

The service container allows you to extend parent services in order to avoid duplicated service definitions:

サービス コンテナを使用すると、サービス定義の重複を避けるために親サービスを拡張できます。
  • YAML
    YAML
  • XML
    XML
  • PHP
    PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# config/services.yaml
services:
    App\Repository\BaseDoctrineRepository:
        abstract:  true
        arguments: ['@doctrine.orm.entity_manager']
        calls:
            - setLogger: ['@logger']

    App\Repository\DoctrineUserRepository:
        # extend the App\Repository\BaseDoctrineRepository service
        parent: App\Repository\BaseDoctrineRepository

    App\Repository\DoctrinePostRepository:
        parent: App\Repository\BaseDoctrineRepository

    # ...

In this context, having a parent service implies that the arguments and method calls of the parent service should be used for the child services. Specifically, the EntityManager will be injected and setLogger() will be called when App\Repository\DoctrineUserRepository is instantiated.

このコンテキストでは、親サービスを持つことは、親サービスの引数とメソッド呼び出しを子サービスに使用する必要があることを意味します。具体的には、EntityManager が注入され、App\Repository\DoctrineUserRepository がインスタンス化されるときに setLogger() が呼び出されます。

All attributes on the parent service are shared with the child except for shared, abstract and tags. These are not inherited from the parent.

親サービスのすべての属性は、共有、抽象、およびタグを除いて子と共有されます。これらは親から継承されません。

Tip

ヒント

In the examples shown, the classes sharing the same configuration also extend from the same parent class in PHP. This isn't necessary at all. You can also extract common parts of similar service definitions into a parent service without also extending a parent class in PHP.

示されている例では、同じ構成を共有するクラスも、PHP の同じ親クラスから拡張されています。これはまったく必要ありません。PHP で親クラスを拡張しなくても、同様のサービス定義の共通部分を親サービスに抽出することもできます。

Overriding Parent Dependencies

There may be times where you want to override what service is injected for one child service only. You can override most settings by specifying it in the child class:

1 つの子サービスに対してのみ注入されるサービスをオーバーライドしたい場合があります。子クラスで指定することにより、ほとんどの設定をオーバーライドできます。
  • YAML
    YAML
  • XML
    XML
  • PHP
    PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# config/services.yaml
services:
    # ...

    App\Repository\DoctrineUserRepository:
        parent: App\Repository\BaseDoctrineRepository

        # overrides the private setting of the parent service
        public: true

        # appends the '@app.username_checker' argument to the parent
        # argument list
        arguments: ['@app.username_checker']

    App\Repository\DoctrinePostRepository:
        parent: App\Repository\BaseDoctrineRepository

        # overrides the first argument (using the special index_N key)
        arguments:
            index_0: '@doctrine.custom_entity_manager'