サービスを作成するファクトリの使用方法¶
Symfony2 のサービスコンテナは、コンストラクタに特定の引数を渡したり、メソッドを呼び出したり、パラメータのセットをしたりできるオブジェクトの生成を制御する強力な方法を用意しています。しかしながら、あなたのオブジェクトを組み立てるのに必要な全てを用意しているわけではありません。こういった状況のために、オブジェクトの作成をするファクトリを使用することができます。そして、直接オブジェクトを初期化するのではなく、ファクトリのメソッドを呼び出すサービスコンテナを使用することができます。
新しい NewsletterManager オブジェクトを設定し、返すファクトリがあるとしましょう。
namespace Acme\HelloBundle\Newsletter;
class NewsletterFactory
{
public function get()
{
$newsletterManager = new NewsletterManager();
// ...
return $newsletterManager;
}
}
NewsletterFactory ファクトリクラスを使用してサービスコンテナを設定することで、 NewsletterManager オブジェクトをサービスとして使用可能にすることができます。
-
YAML
# src/Acme/HelloBundle/Resources/config/services.yml parameters: # ... newsletter_manager.class: Acme\HelloBundle\Newsletter\NewsletterManager newsletter_factory.class: Acme\HelloBundle\Newsletter\NewsletterFactory services: newsletter_manager: class: %newsletter_manager.class% factory_class: %newsletter_factory.class% factory_method: get
-
XML
<!-- src/Acme/HelloBundle/Resources/config/services.xml --> <parameters> <!-- ... --> <parameter key="newsletter_manager.class">Acme\HelloBundle\Newsletter\NewsletterManager</parameter> <parameter key="newsletter_factory.class">Acme\HelloBundle\Newsletter\NewsletterFactory</parameter> </parameters> <services> <service id="newsletter_manager" class="%newsletter_manager.class%" factory-class="%newsletter_factory.class%" factory-method="get" /> </services>
-
PHP
// src/Acme/HelloBundle/Resources/config/services.php use Symfony\Component\DependencyInjection\Definition; // ... $container->setParameter('newsletter_manager.class', 'Acme\HelloBundle\Newsletter\NewsletterManager'); $container->setParameter('newsletter_factory.class', 'Acme\HelloBundle\Newsletter\NewsletterFactory'); $container->setDefinition('newsletter_manager', new Definition( '%newsletter_manager.class%' ))->setFactoryClass( '%newsletter_factory.class%' )->setFactoryMethod( 'get' );
factory_class を介してファクトリに使用するクラスを指定した際は、メソッドはスタティックに呼ばれます。この例のように、ファクトリ自身がインスタンス化される必要があり、そのインスタンス化されたオブジェクトのメソッドを呼び出すには、ファクトリ自体をサービスとして設定してください。
-
YAML
# src/Acme/HelloBundle/Resources/config/services.yml parameters: # ... newsletter_manager.class: Acme\HelloBundle\Newsletter\NewsletterManager newsletter_factory.class: Acme\HelloBundle\Newsletter\NewsletterFactory services: newsletter_factory: class: %newsletter_factory.class% newsletter_manager: class: %newsletter_manager.class% factory_service: newsletter_factory factory_method: get
-
XML
<!-- src/Acme/HelloBundle/Resources/config/services.xml --> <parameters> <!-- ... --> <parameter key="newsletter_manager.class">Acme\HelloBundle\Newsletter\NewsletterManager</parameter> <parameter key="newsletter_factory.class">Acme\HelloBundle\Newsletter\NewsletterFactory</parameter> </parameters> <services> <service id="newsletter_factory" class="%newsletter_factory.class%"/> <service id="newsletter_manager" class="%newsletter_manager.class%" factory-service="newsletter_factory" factory-method="get" /> </services>
-
PHP
// src/Acme/HelloBundle/Resources/config/services.php use Symfony\Component\DependencyInjection\Definition; // ... $container->setParameter('newsletter_manager.class', 'Acme\HelloBundle\Newsletter\NewsletterManager'); $container->setParameter('newsletter_factory.class', 'Acme\HelloBundle\Newsletter\NewsletterFactory'); $container->setDefinition('newsletter_factory', new Definition( '%newsletter_factory.class%' )) $container->setDefinition('newsletter_manager', new Definition( '%newsletter_manager.class%' ))->setFactoryService( 'newsletter_factory' )->setFactoryMethod( 'get' );
Note
ファクトリサービスは、 id の名前で指定されますが、サービス自身への関係は持っていません。そのため、 @ syntax を使用する必要はありません。
ファクトリメソッドへ引数を渡す¶
ファクトリメソッドに引数を渡す必要があれば、サービスコンテナ内で arguments オプションを呼ぶことができます。例えば、前の例の get メソッドが templating サービスを引数として受けるとしますと、次のようになります。
-
YAML
# src/Acme/HelloBundle/Resources/config/services.yml parameters: # ... newsletter_manager.class: Acme\HelloBundle\Newsletter\NewsletterManager newsletter_factory.class: Acme\HelloBundle\Newsletter\NewsletterFactory services: newsletter_factory: class: %newsletter_factory.class% newsletter_manager: class: %newsletter_manager.class% factory_service: newsletter_factory factory_method: get arguments: - @templating
-
XML
<!-- src/Acme/HelloBundle/Resources/config/services.xml --> <parameters> <!-- ... --> <parameter key="newsletter_manager.class">Acme\HelloBundle\Newsletter\NewsletterManager</parameter> <parameter key="newsletter_factory.class">Acme\HelloBundle\Newsletter\NewsletterFactory</parameter> </parameters> <services> <service id="newsletter_factory" class="%newsletter_factory.class%"/> <service id="newsletter_manager" class="%newsletter_manager.class%" factory-service="newsletter_factory" factory-method="get" > <argument type="service" id="templating" /> </service> </services>
-
PHP
// src/Acme/HelloBundle/Resources/config/services.php use Symfony\Component\DependencyInjection\Definition; // ... $container->setParameter('newsletter_manager.class', 'Acme\HelloBundle\Newsletter\NewsletterManager'); $container->setParameter('newsletter_factory.class', 'Acme\HelloBundle\Newsletter\NewsletterFactory'); $container->setDefinition('newsletter_factory', new Definition( '%newsletter_factory.class%' )) $container->setDefinition('newsletter_manager', new Definition( '%newsletter_manager.class%', array(new Reference('templating')) ))->setFactoryService( 'newsletter_factory' )->setFactoryMethod( 'get' );