44Using a Factory to Create Services
55==================================
66
7+ ..versionadded ::2.6
8+ The new ``setFactory `` method was introduced in Symfony 2.6. Refer to older
9+ versions for the syntax for factories prior to 2.6.
10+
711Symfony's Service Container provides a powerful way of controlling the
812creation of objects, allowing you to specify arguments passed to the constructor
913as well as calling methods and setting parameters. Sometimes, however, this
@@ -15,9 +19,9 @@ the class.
1519Suppose you have a factory that configures and returns a new ``NewsletterManager ``
1620object::
1721
18- classNewsletterFactory
22+ classNewsletterManagerFactory
1923 {
20- public functionget ()
24+ publicstatic functioncreateNewsletterManager ()
2125 {
2226 $newsletterManager = new NewsletterManager();
2327
@@ -28,22 +32,17 @@ object::
2832 }
2933
3034To make the ``NewsletterManager `` object available as a service, you can
31- configure the service container to use the `` NewsletterFactory `` factory
32- class :
35+ configure the service container to use the
36+ `` NewsletterFactory::createNewsletterManager() `` factory method :
3337
3438..configuration-block ::
3539
3640 ..code-block ::yaml
3741
38- parameters :
39- # ...
40- newsletter_manager.class :NewsletterManager
41- newsletter_factory.class :NewsletterFactory
4242services :
4343newsletter_manager :
44- class :" %newsletter_manager.class%"
45- factory_class :" %newsletter_factory.class%"
46- factory_method :get
44+ class :NewsletterManager
45+ factory :[NewsletterManagerFactory, createNewsletterManager]
4746
4847 ..code-block ::xml
4948
@@ -52,18 +51,10 @@ class:
5251xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
5352xsi : schemaLocation =" http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd" >
5453
55- <parameters >
56- <!-- ...-->
57- <parameter key =" newsletter_manager.class" >NewsletterManager</parameter >
58- <parameter key =" newsletter_factory.class" >NewsletterFactory</parameter >
59- </parameters >
60-
6154 <services >
62- <service
63- id =" newsletter_manager"
64- class =" %newsletter_manager.class%"
65- factory-class =" %newsletter_factory.class%"
66- factory-method =" get" />
55+ <service id =" newsletter_manager" class =" NewsletterManager" >
56+ <factory class =" NewsletterManagerFactory" method =" createNewsletterManager" />
57+ </service >
6758 </services >
6859 </services >
6960
@@ -72,35 +63,26 @@ class:
7263 use Symfony\Component\DependencyInjection\Definition;
7364
7465 // ...
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');
66+ $definition = new Definition('NewsletterManager');
67+ $definition->setFactory(array('NewsletterManagerFactory', 'createNewsletterManager'));
8168
8269 $container->setDefinition('newsletter_manager', $definition);
8370
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:
71+ Now, the method will be called statically. If the factoryclass itself should
72+ be instantiated and theresulting object's method called, configure the factory
73+ itself as a service. In this case, themethod (e.g. get) should be changed to
74+ be non-static.
8875
8976..configuration-block ::
9077
9178 ..code-block ::yaml
9279
93- parameters :
94- # ...
95- newsletter_manager.class :NewsletterManager
96- newsletter_factory.class :NewsletterFactory
9780services :
98- newsletter_factory :
99- class :" %newsletter_factory.class% "
81+ newsletter_manager.factory :
82+ class :NewsletterManagerFactory
10083newsletter_manager :
101- class :" %newsletter_manager.class%"
102- factory_service :newsletter_factory
103- factory_method :get
84+ class :NewsletterManager
85+ factory :["@newsletter_manager.factory", createNewsletterManager]
10486
10587 ..code-block ::xml
10688
@@ -109,47 +91,29 @@ In this case, the method (e.g. get) should be changed to be non-static:
10991xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
11092xsi : schemaLocation =" http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd" >
11193
112- <parameters >
113- <!-- ...-->
114- <parameter key =" newsletter_manager.class" >NewsletterManager</parameter >
115- <parameter key =" newsletter_factory.class" >NewsletterFactory</parameter >
116- </parameters >
117-
11894 <services >
119- <service id =" newsletter_factory" class =" %newsletter_factory.class% " />
95+ <service id =" newsletter_factory" class =" NewsletterManagerFactory " />
12096
121- <service
122- id =" newsletter_manager"
123- class =" %newsletter_manager.class%"
124- factory-service =" newsletter_factory"
125- factory-method =" get" />
97+ <service id =" newsletter_manager" class =" NewsletterManager" >
98+ <factory service =" NewsletterManager" method =" createNewsletterManager" />
99+ </service >
126100 </services >
127101 </container >
128102
129103 ..code-block ::php
130104
105+ use Symfony\Component\DependencyInjection\Reference;
131106 use Symfony\Component\DependencyInjection\Definition;
132107
133108 // ...
134- $container->setParameter('newsletter_manager.class', 'NewsletterManager');
135- $container->setParameter('newsletter_factory.class', 'NewsletterFactory');
109+ $container->register('newsletter_manager.factory', 'createNewsletterManager');
136110
137- $container->setDefinition('newsletter_factory', new Definition(
138- '%newsletter_factory.class%'
111+ $newsletterManager = new Definition();
112+ $newsletterManager->setFactory(array(
113+ new Reference('newsletter_manager.factory'),
114+ 'createNewsletterManager'
139115 ));
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.
116+ $container->setDefinition('newsletter_manager', $newsletterManager);
153117
154118 Passing Arguments to the Factory Method
155119---------------------------------------
@@ -162,17 +126,13 @@ in the previous example takes the ``templating`` service as an argument:
162126
163127 ..code-block ::yaml
164128
165- parameters :
166- # ...
167- newsletter_manager.class :NewsletterManager
168- newsletter_factory.class :NewsletterFactory
169129services :
170- newsletter_factory :
171- class :" %newsletter_factory.class%"
130+ newsletter_manager.factory :
131+ class :NewsletterManagerFactory
132+
172133newsletter_manager :
173- class :" %newsletter_manager.class%"
174- factory_service :newsletter_factory
175- factory_method :get
134+ class :NewsletterManager
135+ factory :["@newsletter_manager.factory", createNewsletterManager]
176136arguments :
177137 -" @templating"
178138
@@ -183,42 +143,30 @@ in the previous example takes the ``templating`` service as an argument:
183143xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
184144xsi : schemaLocation =" http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd" >
185145
186- <parameters >
187- <!-- ...-->
188- <parameter key =" newsletter_manager.class" >NewsletterManager</parameter >
189- <parameter key =" newsletter_factory.class" >NewsletterFactory</parameter >
190- </parameters >
191-
192146 <services >
193- <service id =" newsletter_factory " class =" %newsletter_factory.class% " />
147+ <service id =" newsletter_manager.factory " class =" NewsletterManagerFactory " />
194148
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" />
149+ <service id =" newsletter_manager" class =" NewsletterManager" >
150+ <factory service =" newsletter_manager.factory" method =" createNewsletterManager" />
151+ <argument type =" service" id =" templating" />
202152 </service >
203153 </services >
204154 </container >
205155
206156 ..code-block ::php
207157
158+ use Symfony\Component\DependencyInjection\Reference;
208159 use Symfony\Component\DependencyInjection\Definition;
209160
210161 // ...
211- $container->setParameter('newsletter_manager.class', 'NewsletterManager');
212- $container->setParameter('newsletter_factory.class', 'NewsletterFactory');
162+ $container->register('newsletter_manager.factory', 'NewsletterManagerFactory');
213163
214- $container->setDefinition('newsletter_factory', new Definition(
215- '%newsletter_factory.class%'
216- ));
217- $container->setDefinition('newsletter_manager', new Definition(
218- '%newsletter_manager.class%',
164+ $newsletterManager = new Definition(
165+ 'NewsletterManager',
219166 array(new Reference('templating'))
220- ))->setFactoryService(
221- 'newsletter_factory'
222- )->setFactoryMethod(
223- 'get'
224167 );
168+ $newsletterManager->setFactory(array(
169+ new Reference('newsletter_manager.factory'),
170+ 'createNewsletterManager'
171+ ));
172+ $container->setDefinition('newsletter_manager', $newsletterManager);