Skip to content

Commit

Permalink
feature #4498 Use new factory syntax (WouterJ)
Browse files Browse the repository at this point in the history
This PR was merged into the 2.6 branch.

Discussion
----------

Use new factory syntax

| Q   | A
| --- | ---
| Doc fix? | no
| New docs? | yes (symfony/symfony#12008)
| Applies to | 2.6+
| Fixed tickets | #4291

Commits
-------

9cbcc2b Applied fixes
d7998b0 Use new factory syntax
  • Loading branch information
weaverryan committed Nov 24, 2014
2 parents 59f0374 + 9cbcc2b commit f748378
Showing 1 changed file with 53 additions and 104 deletions.
157 changes: 53 additions & 104 deletions components/dependency_injection/factories.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
Using a Factory to Create Services
==================================

.. versionadded:: 2.6
The new `Symfony\\Component\\DependencyInjection\\Definition::setFactory`
method was introduced in Symfony 2.6. Refer to older versions for the
syntax for factories prior to 2.6.

Symfony's Service Container provides a powerful way of controlling the
creation of objects, allowing you to specify arguments passed to the constructor
as well as calling methods and setting parameters. Sometimes, however, this
Expand All @@ -15,9 +20,9 @@ the class.
Suppose you have a factory that configures and returns a new ``NewsletterManager``
object::

class NewsletterFactory
class NewsletterManagerFactory
{
public function get()
public static function createNewsletterManager()
{
$newsletterManager = new NewsletterManager();

Expand All @@ -28,22 +33,17 @@ object::
}

To make the ``NewsletterManager`` object available as a service, you can
configure the service container to use the ``NewsletterFactory`` factory
class:
configure the service container to use the
``NewsletterFactory::createNewsletterManager()`` factory method:

.. configuration-block::

.. code-block:: yaml
parameters:
# ...
newsletter_manager.class: NewsletterManager
newsletter_factory.class: NewsletterFactory
services:
newsletter_manager:
class: "%newsletter_manager.class%"
factory_class: "%newsletter_factory.class%"
factory_method: get
class: NewsletterManager
factory: [NewsletterManagerFactory, createNewsletterManager]
.. code-block:: xml
Expand All @@ -52,18 +52,10 @@ class:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<!-- ... -->
<parameter key="newsletter_manager.class">NewsletterManager</parameter>
<parameter key="newsletter_factory.class">NewsletterFactory</parameter>
</parameters>
<services>
<service
id="newsletter_manager"
class="%newsletter_manager.class%"
factory-class="%newsletter_factory.class%"
factory-method="get" />
<service id="newsletter_manager" class="NewsletterManager">
<factory class="NewsletterManagerFactory" method="createNewsletterManager" />
</service>
</services>
</services>
Expand All @@ -72,35 +64,26 @@ class:
use Symfony\Component\DependencyInjection\Definition;
// ...
$container->setParameter('newsletter_manager.class', 'NewsletterManager');
$container->setParameter('newsletter_factory.class', 'NewsletterFactory');
$definition = new Definition('%newsletter_manager.class%');
$definition->setFactoryClass('%newsletter_factory.class%');
$definition->setFactoryMethod('get');
$definition = new Definition('NewsletterManager');
$definition->setFactory(array('NewsletterManagerFactory', 'createNewsletterManager'));
$container->setDefinition('newsletter_manager', $definition);
When you specify the class to use for the factory (via ``factory_class``)
the method will be called statically. If the factory itself should be instantiated
and the resulting object's method called, configure the factory itself as a service.
In this case, the method (e.g. get) should be changed to be non-static:
Now, the method will be called statically. If the factory class itself should
be instantiated and the resulting object's method called, configure the factory
itself as a service. In this case, the method (e.g. get) should be changed to
be non-static.

.. configuration-block::

.. code-block:: yaml
parameters:
# ...
newsletter_manager.class: NewsletterManager
newsletter_factory.class: NewsletterFactory
services:
newsletter_factory:
class: "%newsletter_factory.class%"
newsletter_manager.factory:
class: NewsletterManagerFactory
newsletter_manager:
class: "%newsletter_manager.class%"
factory_service: newsletter_factory
factory_method: get
class: NewsletterManager
factory: ["@newsletter_manager.factory", createNewsletterManager]
.. code-block:: xml
Expand All @@ -109,47 +92,29 @@ In this case, the method (e.g. get) should be changed to be non-static:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<!-- ... -->
<parameter key="newsletter_manager.class">NewsletterManager</parameter>
<parameter key="newsletter_factory.class">NewsletterFactory</parameter>
</parameters>
<services>
<service id="newsletter_factory" class="%newsletter_factory.class%"/>
<service id="newsletter_manager.factory" class="NewsletterManagerFactory" />
<service
id="newsletter_manager"
class="%newsletter_manager.class%"
factory-service="newsletter_factory"
factory-method="get" />
<service id="newsletter_manager" class="NewsletterManager">
<factory service="newsletter_manager.factry" method="createNewsletterManager" />
</service>
</services>
</container>
.. code-block:: php
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Definition;
// ...
$container->setParameter('newsletter_manager.class', 'NewsletterManager');
$container->setParameter('newsletter_factory.class', 'NewsletterFactory');
$container->register('newsletter_manager.factory', 'NewsletterManagerFactory');
$container->setDefinition('newsletter_factory', new Definition(
'%newsletter_factory.class%'
$newsletterManager = new Definition();
$newsletterManager->setFactory(array(
new Reference('newsletter_manager.factory'),
'createNewsletterManager'
));
$container->setDefinition('newsletter_manager', new Definition(
'%newsletter_manager.class%'
))->setFactoryService(
'newsletter_factory'
)->setFactoryMethod(
'get'
);
.. note::

The factory service is specified by its id name and not a reference to
the service itself. So, you do not need to use the @ syntax for this in
YAML configurations.
$container->setDefinition('newsletter_manager', $newsletterManager);
Passing Arguments to the Factory Method
---------------------------------------
Expand All @@ -162,17 +127,13 @@ in the previous example takes the ``templating`` service as an argument:

.. code-block:: yaml
parameters:
# ...
newsletter_manager.class: NewsletterManager
newsletter_factory.class: NewsletterFactory
services:
newsletter_factory:
class: "%newsletter_factory.class%"
newsletter_manager.factory:
class: NewsletterManagerFactory
newsletter_manager:
class: "%newsletter_manager.class%"
factory_service: newsletter_factory
factory_method: get
class: NewsletterManager
factory: ["@newsletter_manager.factory", createNewsletterManager]
arguments:
- "@templating"
Expand All @@ -183,42 +144,30 @@ in the previous example takes the ``templating`` service as an argument:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<!-- ... -->
<parameter key="newsletter_manager.class">NewsletterManager</parameter>
<parameter key="newsletter_factory.class">NewsletterFactory</parameter>
</parameters>
<services>
<service id="newsletter_factory" class="%newsletter_factory.class%"/>
<service id="newsletter_manager.factory" class="NewsletterManagerFactory"/>
<service
id="newsletter_manager"
class="%newsletter_manager.class%"
factory-service="newsletter_factory"
factory-method="get">
<argument type="service" id="templating" />
<service id="newsletter_manager" class="NewsletterManager">
<factory service="newsletter_manager.factory" method="createNewsletterManager"/>
<argument type="service" id="templating"/>
</service>
</services>
</container>
.. code-block:: php
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Definition;
// ...
$container->setParameter('newsletter_manager.class', 'NewsletterManager');
$container->setParameter('newsletter_factory.class', 'NewsletterFactory');
$container->register('newsletter_manager.factory', 'NewsletterManagerFactory');
$container->setDefinition('newsletter_factory', new Definition(
'%newsletter_factory.class%'
));
$container->setDefinition('newsletter_manager', new Definition(
'%newsletter_manager.class%',
$newsletterManager = new Definition(
'NewsletterManager',
array(new Reference('templating'))
))->setFactoryService(
'newsletter_factory'
)->setFactoryMethod(
'get'
);
$newsletterManager->setFactory(array(
new Reference('newsletter_manager.factory'),
'createNewsletterManager'
));
$container->setDefinition('newsletter_manager', $newsletterManager);

0 comments on commit f748378

Please sign in to comment.