Skip to content
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

Improved the docs for the DependencyInjection component #6504

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
68 changes: 54 additions & 14 deletions components/dependency_injection/definitions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
Working with Container Service Definitions
==========================================

Service definitions are the instructions followed by the container to build a
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe "[...] are the instructions describing how the container should build a service. They are not the actual services used by our applications" ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mucha better. Thanks

service, so they are not the actual services used by your application.

Getting and Setting Service Definitions
---------------------------------------

Expand Down Expand Up @@ -32,34 +35,68 @@ with these methods and make changes to it these will be reflected in the
container. If, however, you are creating a new definition then you can add
it to the container using::

$container->setDefinition($id, $definition);
use Symfony\Component\DependencyInjection\Definition;

$definition = new Definition('Acme\Service\MyService');
$container->setDefinition('app.my_service', $definition);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

app.my_service -> acme.my_service

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although this is the component doc, I don't think is wrong to use the app. prefix. After all, you are building an application with this component. Anyway, I'll wait to read more opinions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's keep acme for the components section for now (even more recently added parts of this section consistently use Acme).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code could also be in a bundle, I guess the prefix is more a matter of namespace. app.my_service should match App\Service\MyService so acme looks better indeed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed it to acme.my_service Thanks for your comments.


.. tip::

Registering service definitions is so common that the container provides a
shortcut method called ``register()``:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing the second colon

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Thanks.


$container->register('app.my_service', 'Acme\Service\MyService');

Working with a Definition
-------------------------

Creating a New Definition
~~~~~~~~~~~~~~~~~~~~~~~~~

If you need to create a new definition rather than manipulate one retrieved
from the container then the definition class is :class:`Symfony\\Component\\DependencyInjection\\Definition`.
In addition to manipulating and retrieving existing definitions, you can also
define new service definitions with the :class:`Symfony\\Component\\DependencyInjection\\Definition`
class.

Class
~~~~~

First up is the class of a definition, this is the class of the object returned
when the service is requested from the container.
The first optional argument of the ``Definition`` class is the fully qualified
class name of the object returned when the service is get from the container::
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[...] is requested [...]

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or [...] is fetched [...]


To find out what class is set for a definition::
use Symfony\Component\DependencyInjection\Definition;

$definition = new Definition('Acme\Service\MyService');

If the class is unknown when instantiating the ``Definition`` class, use the
``setClass()`` method to set it later::

$definition->getClass();
$definition->setClass('Acme\Service\MyService');

and to set a different class::
To find out what class is set for a definition::

$definition->setClass($class); // Fully qualified class name as string
$class = $definition->getClass();
// $class = 'Acme\Service\MyService'

Constructor Arguments
~~~~~~~~~~~~~~~~~~~~~

The second optional argument of the ``Definition`` class is an array with the
arguments passed to the constructor of the object returned when the service is
get from the container::
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here


use Symfony\Component\DependencyInjection\Definition;

$definition = new Definition(
'Acme\Service\MyService',
array('argument1' => 'value1', 'argument2' => 'value2')
);

If the arguments are unknown when instantiating the ``Definition`` class or if
you want to add new arguments, use the ``addArgument()`` method, which adds them
at the end of the arguments array::

$definition->addArgument($argument);

To get an array of the constructor arguments for a definition you can use::

$definition->getArguments();
Expand All @@ -69,12 +106,16 @@ or to get a single argument by its position::
$definition->getArgument($index);
// e.g. $definition->getArgument(0) for the first argument

You can add a new argument to the end of the arguments array using::
The argument can be a string, an array, a service parameter by using the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[...] an array or a container parameter [...]

``%parameter_name%`` syntax::

$definition->addArgument($argument);
$definition->addArgument('%kernel_debug%');

The argument can be a string, an array, a service parameter by using ``%parameter_name%``
or a service id by using::
If the argument is another container service, don't use the ``get()`` method to
get the actual service, because it won't be available when defining services.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, it is available but it will to try create the concrete service when it was not built before which can lead to weird behaviour.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it may not be available at all (as it can be registered later). And it can also be defined in an incomplete way.
And finally, the container needs to know about how to define it later, so it needs the id

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I misread this. I thought that "it" referred to the get() method. But anyway, I think we should reword this a bit (not sure what would be the best though).

Instead, use the :class:`Symfony\\Component\\DependencyInjection\\Reference`
class to get a reference to the service available once the service container is
fully built::

use Symfony\Component\DependencyInjection\Reference;

Expand Down Expand Up @@ -139,4 +180,3 @@ the service itself gets loaded. To do so, you can use the

Notice that Symfony will internally call the PHP statement ``require_once``,
which means that your file will be included only once per request.

5 changes: 4 additions & 1 deletion components/dependency_injection/introduction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,10 @@ like this::
// ...
}

Then you can register this as a service as well and pass the ``mailer`` service into it::
Then you can register this as a service as well and pass the ``mailer`` service
into it. Instead of getting the actual ``mailer`` service, which doesn't exist
yet when defining the ``newsletter_manager``, use the ``Reference`` class to
get a reference to the future ``mailer`` service::
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very big sentence. It should be split in multiple shorter ones, e.g: "When defining the newsletter_manager service, the mailer service does not exists yet. Use the Reference class to tell the container to inject the mailer service when it initializes the newsletter manager.".

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice proposal! Thanks.


use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
Expand Down