跳到內容

如何使用父服務管理常見依賴關係

編輯此頁

當您為應用程式新增更多功能時,您很可能會開始擁有相關的類別,這些類別共用一些相同的依賴關係。例如,您可能有多個儲存庫類別需要 doctrine.orm.entity_manager 服務和一個可選的 logger 服務

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// src/Repository/BaseDoctrineRepository.php
namespace App\Repository;

use Doctrine\ORM\EntityManager;
use Psr\Log\LoggerInterface;

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

    public function __construct(
        protected EntityManager $entityManager,
    ) {
    }

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

    // ...
}

您的子服務類別可能如下所示

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
{
    // ...
}

服務容器允許您擴展父服務,以避免重複的服務定義

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

    # ...

在這種情況下,擁有一個 parent 服務意味著父服務的參數和方法呼叫應該用於子服務。具體來說,當 App\Repository\DoctrineUserRepository 被實例化時,將注入 EntityManager 並且會呼叫 setLogger()

父服務上的所有屬性都與子服務共享,除了 sharedabstracttags。這些屬性不會從父服務繼承。

提示

在顯示的範例中,共享相同配置的類別也在 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'
本作品,包括程式碼範例,依 Creative Commons BY-SA 3.0 授權條款發佈。
目錄
    版本