Skip to content

Moved advanced service container section into components #1530

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 2 additions & 133 deletions book/service_container.rst
Original file line number Diff line number Diff line change
Expand Up @@ -876,142 +876,10 @@ the framework.
the ``swiftmailer`` key invokes the service extension from the
``SwiftmailerBundle``, which registers the ``mailer`` service.

.. index::
single: Service Container; Advanced configuration

Advanced Container Configuration
--------------------------------

As we've seen, defining services inside the container is easy, generally
involving a ``service`` configuration key and a few parameters. However,
the container has several other tools available that help to *tag* services
for special functionality, create more complex services, and perform operations
after the container is built.

Marking Services as public / private
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When defining services, you'll usually want to be able to access these definitions
within your application code. These services are called ``public``. For example,
the ``doctrine`` service registered with the container when using the DoctrineBundle
is a public service as you can access it via::

$doctrine = $container->get('doctrine');

However, there are use-cases when you don't want a service to be public. This
is common when a service is only defined because it could be used as an
argument for another service.

.. note::

If you use a private service as an argument to more than one other service,
this will result in two different instances being used as the instantiation
of the private service is done inline (e.g. ``new PrivateFooBar()``).

Simply said: A service will be private when you do not want to access it
directly from your code.

Here is an example:

.. configuration-block::

.. code-block:: yaml

services:
foo:
class: Acme\HelloBundle\Foo
public: false

.. code-block:: xml

<service id="foo" class="Acme\HelloBundle\Foo" public="false" />

.. code-block:: php

$definition = new Definition('Acme\HelloBundle\Foo');
$definition->setPublic(false);
$container->setDefinition('foo', $definition);

Now that the service is private, you *cannot* call::

$container->get('foo');

However, if a service has been marked as private, you can still alias it (see
below) to access this service (via the alias).

.. note::

Services are by default public.

Aliasing
~~~~~~~~

When using core or third party bundles within your application, you may want
to use shortcuts to access some services. You can do so by aliasing them and,
furthermore, you can even alias non-public services.

.. configuration-block::

.. code-block:: yaml

services:
foo:
class: Acme\HelloBundle\Foo
bar:
alias: foo

.. code-block:: xml

<service id="foo" class="Acme\HelloBundle\Foo"/>

<service id="bar" alias="foo" />

.. code-block:: php

$definition = new Definition('Acme\HelloBundle\Foo');
$container->setDefinition('foo', $definition);

$containerBuilder->setAlias('bar', 'foo');

This means that when using the container directly, you can access the ``foo``
service by asking for the ``bar`` service like this::

$container->get('bar'); // Would return the foo service

Requiring files
~~~~~~~~~~~~~~~

There might be use cases when you need to include another file just before
the service itself gets loaded. To do so, you can use the ``file`` directive.

.. configuration-block::

.. code-block:: yaml

services:
foo:
class: Acme\HelloBundle\Foo\Bar
file: %kernel.root_dir%/src/path/to/file/foo.php

.. code-block:: xml

<service id="foo" class="Acme\HelloBundle\Foo\Bar">
<file>%kernel.root_dir%/src/path/to/file/foo.php</file>
</service>

.. code-block:: php

$definition = new Definition('Acme\HelloBundle\Foo\Bar');
$definition->setFile('%kernel.root_dir%/src/path/to/file/foo.php');
$container->setDefinition('foo', $definition);

Notice that symfony will internally call the PHP function require_once
which means that your file will be included only once per request.

.. _book-service-container-tags:

Tags (``tags``)
~~~~~~~~~~~~~~~
---------------

In the same way that a blog post on the Web might be tagged with things such
as "Symfony" or "PHP", services configured in your container can also be
Expand Down Expand Up @@ -1074,5 +942,6 @@ Learn more
* :doc:`/components/dependency_injection/factories`
* :doc:`/components/dependency_injection/parentservices`
* :doc:`/cookbook/controller/service`
* :doc:`/components/dependency_injection/advanced`

.. _`service-oriented architecture`: http://wikipedia.org/wiki/Service-oriented_architecture
125 changes: 125 additions & 0 deletions components/dependency_injection/advanced.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
.. index::
single: Dependency Injection; Advanced configuration

Advanced Container Configuration
================================

Marking Services as public / private
------------------------------------

When defining services, you'll usually want to be able to access these definitions
within your application code. These services are called ``public``. For example,
the ``doctrine`` service registered with the container when using the DoctrineBundle
is a public service as you can access it via::

$doctrine = $container->get('doctrine');

However, there are use-cases when you don't want a service to be public. This
is common when a service is only defined because it could be used as an
argument for another service.

.. note::

If you use a private service as an argument to more than one other service,
this will result in two different instances being used as the instantiation
of the private service is done inline (e.g. ``new PrivateFooBar()``).

Simply said: A service will be private when you do not want to access it
directly from your code.

Here is an example:

.. configuration-block::

.. code-block:: yaml

services:
foo:
class: Example\Foo
public: false

.. code-block:: xml

<service id="foo" class="Example\Foo" public="false" />

.. code-block:: php

$definition = new Definition('Example\Foo');
$definition->setPublic(false);
$container->setDefinition('foo', $definition);

Now that the service is private, you *cannot* call::

$container->get('foo');

However, if a service has been marked as private, you can still alias it (see
below) to access this service (via the alias).

.. note::

Services are by default public.

Aliasing
--------

You may sometimes want to use shortcuts to access some services. You can
do so by aliasing them and, furthermore, you can even alias non-public
services.

.. configuration-block::

.. code-block:: yaml

services:
foo:
class: Example\Foo
bar:
alias: foo

.. code-block:: xml

<service id="foo" class="Example\Foo"/>

<service id="bar" alias="foo" />

.. code-block:: php

$definition = new Definition('Example\Foo');
$container->setDefinition('foo', $definition);

$containerBuilder->setAlias('bar', 'foo');

This means that when using the container directly, you can access the ``foo``
service by asking for the ``bar`` service like this::

$container->get('bar'); // Would return the foo service

Requiring files
---------------

There might be use cases when you need to include another file just before
the service itself gets loaded. To do so, you can use the ``file`` directive.

.. configuration-block::

.. code-block:: yaml

services:
foo:
class: Example\Foo\Bar
file: %kernel.root_dir%/src/path/to/file/foo.php

.. code-block:: xml

<service id="foo" class="Example\Foo\Bar">
<file>%kernel.root_dir%/src/path/to/file/foo.php</file>
</service>

.. code-block:: php

$definition = new Definition('Example\Foo\Bar');
$definition->setFile('%kernel.root_dir%/src/path/to/file/foo.php');
$container->setDefinition('foo', $definition);

Notice that symfony will internally call the PHP function require_once
which means that your file will be included only once per request.
1 change: 1 addition & 0 deletions components/dependency_injection/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@
tags
factories
parentservices
advanced