2021年4月3日土曜日

PHP:Symfony-04

1.DIコンテナ

Symfony 4 のDI機能については config ディレクトリ内の services.yaml で定義されている

parameters:

services:
    # default configuration for services in *this* file
    _defaults:
        autowiretrue      # Automatically injects dependencies in your services.
        autoconfiguretrue # Automatically registers your services as commands, event subscribers, etc.

    # 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/'
            - '../src/Entity/'
            - '../src/Kernel.php'
            - '../src/Tests/'

    # 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

2.実際の例 

名前空間: App\Service

ファイル: src/Service/SampleService.php

<?php

namespace App\Service;
 
class SampleService
{
    public function helloWorld(): string
    {
        return 'hello world.';
    }
 
}


コントローラ上のルーティングから利用

    /**
     * @Route("/service/useService1", methods={"GET"})
     */
    public function useSerivce1(\App\Service\SampleService $sampleService)
    {
        $result = $sampleService->helloWorld();
        
        return $this->render('/service/use_service.html.twig', [
            'body' => $result
        ]);
    }


/serivce/use_service.html.twig

<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <title>{{ title|default('default title')}}</title>
    </head>
    <body>
        {{ body }}
    </body>
</html>


コンストラクタでのインジェクションを試してみます。クラス内で恒常的に使うのに良いです。

    // 利用するサービスクラスをコンストラクタインジェクションする
    private $sampleService;
    
    public function __construct(\App\Service\SampleService $sampleService)
    {
        $this->sampleService = $sampleService;
    }
    
    /**
     * @Route("/service/useService2", methods={"GET"})
     */
    public function useSerivce2()
    {
        $result = $this->sampleService->helloWorld();
        
        return $this->render('/service/use_service.html.twig', [
            'body' => $result
        ]);
    }


設定値の注入

<?php
namespace App\Service;
 
class MailService
{
    private $from_address;
 
    public function __construct($from_address)
    {
        $this->from_address = $from_address;
    }
}


parameters:
    from_address'xxx@yyy.zzz'

services:
    # default configuration for services in *this* file
    _defaults:
        autowiretrue      # Automatically injects dependencies in your services.
        autoconfiguretrue # Automatically registers your services as commands, event subscribers, etc.

    # 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/'
            - '../src/Entity/'
            - '../src/Kernel.php'
            - '../src/Tests/'

    App\Service\MailService:
        arguments:
            $from_address'%from_address%'



コンテナから直接取得する

コンテナに登録済みのオブジェクトは直接取得する事も出来ます。依存性は高くなりますがそうしたい場合もあるかと思いますので記載しておきます。

$sampleService = $this->container->get('App\Service\SampleService');

$from_address = $this->getParameter('from_address');

なお、上記の $this->container->get() で取りに行く方法はコントローラ内では制限が有り利用できない。