44Using a Factory to Create Services
55==================================
66
7+ ..versionadded ::2.6
8+ The new `Symfony\\Component\\DependencyInjection\\Definition::setFactory `
9+ method was introduced in Symfony 2.6. Refer to older versions for the
10+ syntax for factories prior to 2.6.
11+
712Symfony's Service Container provides a powerful way of controlling the
813creation of objects, allowing you to specify arguments passed to the constructor
914as well as calling methods and setting parameters. Sometimes, however, this
@@ -15,9 +20,9 @@ the class.
1520Suppose you have a factory that configures and returns a new ``NewsletterManager ``
1621object::
1722
18- classNewsletterFactory
23+ classNewsletterManagerFactory
1924 {
20- public functionget ()
25+ publicstatic functioncreateNewsletterManager ()
2126 {
2227 $newsletterManager = new NewsletterManager();
2328
@@ -28,22 +33,17 @@ object::
2833 }
2934
3035To make the ``NewsletterManager `` object available as a service, you can
31- configure the service container to use the `` NewsletterFactory `` factory
32- class :
36+ configure the service container to use the
37+ `` NewsletterFactory::createNewsletterManager() `` factory method :
3338
3439..configuration-block ::
3540
3641 ..code-block ::yaml
3742
38- parameters :
39- # ...
40- newsletter_manager.class :NewsletterManager
41- newsletter_factory.class :NewsletterFactory
4243services :
4344newsletter_manager :
44- class :" %newsletter_manager.class%"
45- factory_class :" %newsletter_factory.class%"
46- factory_method :get
45+ class :NewsletterManager
46+ factory :[NewsletterManagerFactory, createNewsletterManager]
4747
4848 ..code-block ::xml
4949
@@ -52,18 +52,10 @@ class:
5252xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
5353xsi : schemaLocation =" http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd" >
5454
55- <parameters >
56- <!-- ...-->
57- <parameter key =" newsletter_manager.class" >NewsletterManager</parameter >
58- <parameter key =" newsletter_factory.class" >NewsletterFactory</parameter >
59- </parameters >
60-
6155 <services >
62- <service
63- id =" newsletter_manager"
64- class =" %newsletter_manager.class%"
65- factory-class =" %newsletter_factory.class%"
66- factory-method =" get" />
56+ <service id =" newsletter_manager" class =" NewsletterManager" >
57+ <factory class =" NewsletterManagerFactory" method =" createNewsletterManager" />
58+ </service >
6759 </services >
6860 </services >
6961
@@ -72,35 +64,26 @@ class:
7264 use Symfony\Component\DependencyInjection\Definition;
7365
7466 // ...
75- $container->setParameter('newsletter_manager.class', 'NewsletterManager');
76- $container->setParameter('newsletter_factory.class', 'NewsletterFactory');
77-
78- $definition = new Definition('%newsletter_manager.class%');
79- $definition->setFactoryClass('%newsletter_factory.class%');
80- $definition->setFactoryMethod('get');
67+ $definition = new Definition('NewsletterManager');
68+ $definition->setFactory(array('NewsletterManagerFactory', 'createNewsletterManager'));
8169
8270 $container->setDefinition('newsletter_manager', $definition);
8371
84- When you specify the class to use for the factory(via `` factory_class ``)
85- themethod will be called statically. If the factory itself should be instantiated
86- and the resulting object's method called, configure thefactory itself as a service.
87- In this case, the method (e.g. get) should bechanged to be non-static:
72+ Now, the method will be called statically. If the factoryclass itself should
73+ be instantiated and theresulting object's method called, configure the factory
74+ itself as a service. In this case, themethod (e.g. get) should be changed to
75+ be non-static.
8876
8977..configuration-block ::
9078
9179 ..code-block ::yaml
9280
93- parameters :
94- # ...
95- newsletter_manager.class :NewsletterManager
96- newsletter_factory.class :NewsletterFactory
9781services :
98- newsletter_factory :
99- class :" %newsletter_factory.class% "
82+ newsletter_manager.factory :
83+ class :NewsletterManagerFactory
10084newsletter_manager :
101- class :" %newsletter_manager.class%"
102- factory_service :newsletter_factory
103- factory_method :get
85+ class :NewsletterManager
86+ factory :["@newsletter_manager.factory", createNewsletterManager]
10487
10588 ..code-block ::xml
10689
@@ -109,47 +92,29 @@ In this case, the method (e.g. get) should be changed to be non-static:
10992xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
11093xsi : schemaLocation =" http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd" >
11194
112- <parameters >
113- <!-- ...-->
114- <parameter key =" newsletter_manager.class" >NewsletterManager</parameter >
115- <parameter key =" newsletter_factory.class" >NewsletterFactory</parameter >
116- </parameters >
117-
11895 <services >
119- <service id =" newsletter_factory " class =" %newsletter_factory.class% " />
96+ <service id =" newsletter_manager.factory " class =" NewsletterManagerFactory " />
12097
121- <service
122- id =" newsletter_manager"
123- class =" %newsletter_manager.class%"
124- factory-service =" newsletter_factory"
125- factory-method =" get" />
98+ <service id =" newsletter_manager" class =" NewsletterManager" >
99+ <factory service =" newsletter_manager.factry" method =" createNewsletterManager" />
100+ </service >
126101 </services >
127102 </container >
128103
129104 ..code-block ::php
130105
106+ use Symfony\Component\DependencyInjection\Reference;
131107 use Symfony\Component\DependencyInjection\Definition;
132108
133109 // ...
134- $container->setParameter('newsletter_manager.class', 'NewsletterManager');
135- $container->setParameter('newsletter_factory.class', 'NewsletterFactory');
110+ $container->register('newsletter_manager.factory', 'NewsletterManagerFactory');
136111
137- $container->setDefinition('newsletter_factory', new Definition(
138- '%newsletter_factory.class%'
112+ $newsletterManager = new Definition();
113+ $newsletterManager->setFactory(array(
114+ new Reference('newsletter_manager.factory'),
115+ 'createNewsletterManager'
139116 ));
140- $container->setDefinition('newsletter_manager', new Definition(
141- '%newsletter_manager.class%'
142- ))->setFactoryService(
143- 'newsletter_factory'
144- )->setFactoryMethod(
145- 'get'
146- );
147-
148- ..note ::
149-
150- The factory service is specified by its id name and not a reference to
151- the service itself. So, you do not need to use the @ syntax for this in
152- YAML configurations.
117+ $container->setDefinition('newsletter_manager', $newsletterManager);
153118
154119 Passing Arguments to the Factory Method
155120---------------------------------------
@@ -162,17 +127,13 @@ in the previous example takes the ``templating`` service as an argument:
162127
163128 ..code-block ::yaml
164129
165- parameters :
166- # ...
167- newsletter_manager.class :NewsletterManager
168- newsletter_factory.class :NewsletterFactory
169130services :
170- newsletter_factory :
171- class :" %newsletter_factory.class%"
131+ newsletter_manager.factory :
132+ class :NewsletterManagerFactory
133+
172134newsletter_manager :
173- class :" %newsletter_manager.class%"
174- factory_service :newsletter_factory
175- factory_method :get
135+ class :NewsletterManager
136+ factory :["@newsletter_manager.factory", createNewsletterManager]
176137arguments :
177138 -" @templating"
178139
@@ -183,42 +144,30 @@ in the previous example takes the ``templating`` service as an argument:
183144xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
184145xsi : schemaLocation =" http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd" >
185146
186- <parameters >
187- <!-- ...-->
188- <parameter key =" newsletter_manager.class" >NewsletterManager</parameter >
189- <parameter key =" newsletter_factory.class" >NewsletterFactory</parameter >
190- </parameters >
191-
192147 <services >
193- <service id =" newsletter_factory " class =" %newsletter_factory.class% " />
148+ <service id =" newsletter_manager.factory " class =" NewsletterManagerFactory " />
194149
195- <service
196- id =" newsletter_manager"
197- class =" %newsletter_manager.class%"
198- factory-service =" newsletter_factory"
199- factory-method =" get" >
200-
201- <argument type =" service" id =" templating" />
150+ <service id =" newsletter_manager" class =" NewsletterManager" >
151+ <factory service =" newsletter_manager.factory" method =" createNewsletterManager" />
152+ <argument type =" service" id =" templating" />
202153 </service >
203154 </services >
204155 </container >
205156
206157 ..code-block ::php
207158
159+ use Symfony\Component\DependencyInjection\Reference;
208160 use Symfony\Component\DependencyInjection\Definition;
209161
210162 // ...
211- $container->setParameter('newsletter_manager.class', 'NewsletterManager');
212- $container->setParameter('newsletter_factory.class', 'NewsletterFactory');
163+ $container->register('newsletter_manager.factory', 'NewsletterManagerFactory');
213164
214- $container->setDefinition('newsletter_factory', new Definition(
215- '%newsletter_factory.class%'
216- ));
217- $container->setDefinition('newsletter_manager', new Definition(
218- '%newsletter_manager.class%',
165+ $newsletterManager = new Definition(
166+ 'NewsletterManager',
219167 array(new Reference('templating'))
220- ))->setFactoryService(
221- 'newsletter_factory'
222- )->setFactoryMethod(
223- 'get'
224168 );
169+ $newsletterManager->setFactory(array(
170+ new Reference('newsletter_manager.factory'),
171+ 'createNewsletterManager'
172+ ));
173+ $container->setDefinition('newsletter_manager', $newsletterManager);