44Using a Factory to Create Services
55==================================
66
7- Symfony's Service Container provides a powerful way of controlling the
8- creation of objects, allowing you to specify arguments passed to the constructor
9- as well as calling methods and setting parameters. Sometimes, however, this
10- will not provide you with everything you need to construct your objects.
11- For this situation, you can use a factory to create the object and tell
12- the service container to call a method on the factory rather than directly
13- instantiating the class.
7+ Symfony's Service Container provides multiple features to control the creation
8+ of objects, allowing you to specify arguments passed to the constructor as well
9+ as calling methods and setting parameters.
10+
11+ However, sometimes you need to apply the `factory design pattern `_ to delegate
12+ the object creation to some special object called "the factory". In those cases,
13+ the service container can call a method on your factory to create the object
14+ rather than directly instantiating the class.
15+
16+ Static Factories
17+ ----------------
1418
1519Suppose you have a factory that configures and returns a new ``NewsletterManager ``
1620object by calling the static ``createNewsletterManager() `` method::
@@ -27,9 +31,9 @@ object by calling the static ``createNewsletterManager()`` method::
2731 }
2832 }
2933
30- To make the ``NewsletterManager `` object available as a service, you can
31- configure the service container to use the
32- `` NewsletterManagerStaticFactory::createNewsletterManager() `` factory method :
34+ To make the ``NewsletterManager `` object available as a service, use the
35+ `` factory `` option to define which method of which class must be called to
36+ create its object :
3337
3438.. configuration-block ::
3539
@@ -40,7 +44,7 @@ configure the service container to use the
4044 # ...
4145
4246 App\Email\NewsletterManager :
43- # call the static method
47+ # the first argument is the class and the second argument is the static method
4448 factory : ['App\Email\NewsletterManagerStaticFactory', 'createNewsletterManager']
4549
4650 .. code-block :: xml
@@ -54,7 +58,7 @@ configure the service container to use the
5458
5559 <services >
5660 <service id =" App\Email\NewsletterManager" >
57- <!-- call the static method -->
61+ <!-- the first argument is the class and the second argument is the static method -->
5862 <factory class =" App\Email\NewsletterManagerStaticFactory" method =" createNewsletterManager" />
5963
6064 <!-- if the factory class is the same as the service class, you can omit
@@ -77,8 +81,8 @@ configure the service container to use the
7781 return function(ContainerConfigurator $configurator) {
7882 $services = $configurator->services();
7983
80- // call the static method
8184 $services->set(NewsletterManager::class)
85+ // the first argument is the class and the second argument is the static method
8286 ->factory([NewsletterManagerStaticFactory::class, 'createNewsletterManager']);
8387 };
8488
@@ -91,11 +95,11 @@ configure the service container to use the
9195 the configured class name may be used by compiler passes and therefore
9296 should be set to a sensible value.
9397
94- If your factory is not using a static function to configure and create your
95- service, but a regular method, you can instantiate the factory itself as a
96- service too. Later, in the ":ref: `factories-passing-arguments-factory-method `"
97- section, you learn how you can inject arguments in this method.
98+ Non-Static Factories
99+ --------------------
98100
101+ If your factory is using a regular method instead of a static one to configure
102+ and create the service, instantiate the factory itself as a service too.
99103Configuration of the service container then looks like this:
100104
101105.. configuration-block ::
@@ -106,10 +110,12 @@ Configuration of the service container then looks like this:
106110 services :
107111 # ...
108112
113+ # first, create a service for the factory
109114 App\Email\NewsletterManagerFactory : ~
110115
116+ # second, use the factory service as the first argument of the 'factory'
117+ # option and the factory method as the second argument
111118 App\Email\NewsletterManager :
112- # call a method on the specified factory service
113119 factory : ['@App\Email\NewsletterManagerFactory', 'createNewsletterManager']
114120
115121 .. code-block :: xml
@@ -122,10 +128,12 @@ Configuration of the service container then looks like this:
122128 https://symfony.com/schema/dic/services/services-1.0.xsd" >
123129
124130 <services >
131+ <!-- first, create a service for the factory -->
125132 <service id =" App\Email\NewsletterManagerFactory" />
126133
134+ <!-- second, use the factory service as the first argument of the 'factory'
135+ option and the factory method as the second argument -->
127136 <service id =" App\Email\NewsletterManager" >
128- <!-- call a method on the specified factory service -->
129137 <factory service =" App\Email\NewsletterManagerFactory"
130138 method =" createNewsletterManager"
131139 />
@@ -144,15 +152,20 @@ Configuration of the service container then looks like this:
144152 return function(ContainerConfigurator $configurator) {
145153 $services = $configurator->services();
146154
155+ // first, create a service for the factory
147156 $services->set(NewsletterManagerFactory::class);
148157
149- // call a method on the specified factory service
158+ // second, use the factory service as the first argument of the 'factory'
159+ // method and the factory method as the second argument
150160 $services->set(NewsletterManager::class)
151161 ->factory([ref(NewsletterManagerFactory::class), 'createNewsletterManager']);
152162 };
153163
154164 .. _factories-invokable :
155165
166+ Invokable Factories
167+ -------------------
168+
156169Suppose you now change your factory method to ``__invoke() `` so that your
157170factory service can be used as a callback::
158171
@@ -230,8 +243,8 @@ Passing Arguments to the Factory Method
230243 that's enabled for your service.
231244
232245If you need to pass arguments to the factory method you can use the ``arguments ``
233- options . For example, suppose the ``createNewsletterManager() `` method in the previous
234- example takes the ``templating `` service as an argument:
246+ option . For example, suppose the ``createNewsletterManager() `` method in the
247+ previous examples takes the ``templating `` service as an argument:
235248
236249.. configuration-block ::
237250
@@ -281,3 +294,4 @@ example takes the ``templating`` service as an argument:
281294 ;
282295 };
283296
297+ .. _`factory design pattern` : https://en.wikipedia.org/wiki/Factory_(object-oriented_programming)
0 commit comments