From b41d629d59bf654565cce61ab1945f13b728774e Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sat, 12 Feb 2011 16:24:11 -0600 Subject: [PATCH 1/7] [service_container] Initial import of the service container guide and additions to the glossary. --- glossary.rst | 18 +- guides/service_container.rst | 711 +++++++++++++++++++++++++++++++++++ 2 files changed, 728 insertions(+), 1 deletion(-) create mode 100644 guides/service_container.rst diff --git a/glossary.rst b/glossary.rst index 0ceb697970f..8a1492770c8 100644 --- a/glossary.rst +++ b/glossary.rst @@ -23,4 +23,20 @@ Glossary A *Front Controller* is a short PHP that lives in the web directory of your project. Typically, *all* requests are handled by executing the same front controller, whose job is to bootstrap the Symfony - application. \ No newline at end of file + application. + + Service + A *Service* is a generic term for any PHP object that performs a + specific task. In Symfony2, services are often configured and retrieved + from the service container. An application that has many decoupled + services is said to follow a `service-oriented architecture`_ + + Service Container + A *Service Container*, also known as a *Dependency Injection Container*, + is a special object that manages the instantiation of services inside + an application. Instead of creating services directly, the developer + *trains* the service container (via configuration) on how to create + the services. The service container eases takes care of lazily instantiating + and injecting dependent services. + +.. _`service-oriented architecture`: http://wikipedia.org/wiki/Service-oriented_architecture \ No newline at end of file diff --git a/guides/service_container.rst b/guides/service_container.rst new file mode 100644 index 00000000000..5e9e77df30e --- /dev/null +++ b/guides/service_container.rst @@ -0,0 +1,711 @@ +.. index:: + single: Service Container + single: Dependency Injection Container + +The Service Container +===================== + +A modern PHP application is full of objects. One object may facilitate the +delivery of email messages while another may allow you to persist information +into a database. In your application, you may create an object that manages +your product inventory, or another object that processes data from a third-party +API. The point is that a modern application does many things and is organized +into many object that handle each task. + +In this guide, we'll talk about a special PHP object in Symfony2 that helps +your instantiate, organize and retrieve the many object of your application. +This object, called a service container, will allow you to standardize and +centralize the way objects are constructed in your application. The container +makes your life easier, is super fast, and emphasizes and architecture that +promotes reusable and decoupled code. And since all core Symfony2 classes +use the container, you'll learn how to extend, configure and use any object +in Symfony2. In large part, the service container is the biggest contributor +to the speed and extensability of Symfony2. + +Finally, configuring and using the service container is easy. By the end +of this chapter, you'll be comfortable creating your own objects via the +container and customizing objects from any third-party bundle. You'll begin +writing code that is more reusable, testable and decoupled, simply because +the service container makes writing good code so easy. + +.. index:: + single: Service Container; What is a service? + +What is a Service? +------------------ + +Put simply, a :term:`Service` is any PHP object that does something. It's +a purposefully-generic name used in computer science to describe an object +that's created for a specific purpose (e.g. delivering emails). You don't +have to do anything specialy to make a service: simply write a PHP class +with some code that accomplishes a specific task. Congrtulations, you've +just created a service! + +So what's the big deal then? The advantage of thinking about "services" is +that you begin to think about separating each piece of functionality in your +application into a series of services. Since each service does just one job, +you can easily access each service and use its functionality wherever you +need it. Each service can also be more easily tested and configured since +it's separated from the other functionality in your application. This idea +is called `service-oriented architecture`_ and is not unique to Symfony2 +or even PHP. Structuring your application around a set of independent service +classes is well-known and trusted object-oriented best-practice. These skills +are key to being a good developer in almost any language. + +.. index:: + single: Service Container; What is? + +What is a Service Container? +---------------------------- + +A :term:`Service Container` (or *dependency injection container*) is simply +a PHP object that manages the instantiation of services (i.e. objects). +For example, suppose we have a simple PHP class that delivers email messages. +Without a service container, we must manually create the object whenever +we need it: + +.. code-block:: + + use Sensio\HelloBundle\Mailer; + + $mailer = new Mailer('sendmail'); + $mailer->send('ryan@foobar.net', ... ); + +This is easy enough. The imaginary ``Mailer`` class allows us to configure +the method used to deliver the email messages (e.g. ``sendmail``, ``smtp``, etc). +But what if we wanted to use the mailer service somewhere else? We certainly +don't want to repeat the mailer configuration *every* time we need to use +the ``Mailer`` object. What if we needed to change the ``transport`` from +``sendmail`` to ``smtp`` everywhere in the application? We'd need to hunt +down every place we create a ``Mailer`` service and change it. + +.. index:: + single: Service Container; Configuring services + +Creating/Configuring Services in the Container +---------------------------------------------- + +A better answer is to let the service container create the ``Mailer`` object +for you. In order for this to work, we must *teach* the container how to +create the ``Mailer`` service. This is done via configuration, which can +be specified in YAML, XML or PHP: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/config.yml + services: + my_mailer: + class: Sensio\HelloBundle\Mailer + arguments: [sendmail] + + .. code-block:: xml + + + + + sendmail + + + + .. code-block:: php + + // app/config/config.php + use Symfony\Component\DependencyInjection\Definition; + + $container->setDefinition('my_mailer', new Definition( + 'Sensio\HelloBundle\Mailer', + array('sendmail') + )); + +.. note:: + + When Symfony2 initializes, it builds the service container using the + application configuration (``app/config/config.yml`` by default). The + exact file that's loaded is dicated by the ``AppKernel::loadConfig()`` + method, which loads an environment-specific configuration file (e.g. + ``config_dev.yml`` for the ``dev`` environment or ``config_prod.yml`` + for ``prod``). + +An instance of the ``Sensio\HelloBundle\Mailer`` object is now available via +the service container. Since the container is available in any traditional +Symfony2 controller, we can easily access the new ``my_mailer`` service:: + + class HelloController extends Controller + { + // ... + + public function sendEmailAction() + { + // ... + $mailer = $this->container->get('my_mailer'); + $mailer->send('ryan@foobar.net', ... ); + } + } + +.. tip:: + + When using a tranditional controller, there's an even shorter way to + access a service from the container. This is exactly equivalent to the + above method, but with less keystrokes:: + + $mailer = $this->get('my_mailer'); + +When we ask for the ``my_mailer`` service from the container, the container +constructs the object and returns it. This is another major advantage of +using the service container. Namely, a service is *never* constructed until +its needed. If you define a service and never use it on a request, the service +is never created. This saves memory and increases the speed of your application. +This also means that there's very little or no performance hit for defining +lot's of services. Services that are never used are never constructed. + +As an added bonus, the ``Mailer`` service is only created once and the same +instance is returned each time you ask for the service. This is almost always +the behavior you'll need (it's more flexible and performant), but we'll learn +later how you can configure a service that has multiple instances. + +Service Parameters +------------------ + +The creation of new services (i.e. objects) via the container is pretty +straightforward. Parameters make defining services more organized and flexible: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/config.yml + parameters: + my_mailer.class: Sensio\HelloBundle\Mailer + my_mailer.transport: sendmail + + services: + my_mailer: + class: %my_mailer.class% + arguments: [%my_mailer.transport%] + + .. code-block:: xml + + + + Sensio\HelloBundle\Mailer + sendmailxml + + + + + %my_mailer.transport% + + + + .. code-block:: php + + // app/config/config.php + use Symfony\Component\DependencyInjection\Definition; + + $container->setParameter('my_mailer.class', 'Sensio\HelloBundle\Mailer'); + $container->setParameter('my_mailer.transport', 'sendmailphp'); + + $container->setDefinition('my_mailer', new Definition( + '%my_mailer.class%', + array('%my_mailer.transport%') + )); + +The end result is exactly the same as before - the difference is only in +*how* we defined the service. By surrounding the ``my_mailer.class`` and +``my_mailer.transport`` strings in percent (``%``) signs, the container knows +to look for parameters with those names. When the container is built, it +looks up the value of each parameter and uses it in the service definition. + +The purpose of parameters is to feed information into services. Of course +there was nothing wrong with defining the service without using any parameters. +Parameters, however, have several advantages: + +* separation and organization of all of the service "options" under a single + ``parameters`` key; + +* parameter values can be used in multiple service definitions; + +* when creating a service in a bundle (we'll show this shortly), using parameters + allows the service to be easily customized in your application; + +The choice of using or not using parameters is up to you. High-quality +third-party bundles will *always* use parameters as they make the service +stored in the container more configurable. For the services in your application, +however, you may not need the flexibility of parameters. + +Importing other Container Configuration Resources +------------------------------------------------- + +.. tip:: + + In this section, we'll refer to service configuration files as *resources*. + This is to highlight that fact that, while most configuration resources + will be files (e.g. YAML, XML, PHP), Symfony2 is so flexible that configuration + could be loaded from anywhere (e.g. a database or even via an external + web service). + +The service container is built using a single configuration resource +(``app/config/config.yml`` by default). All other service configuration( +(including the core Symfony2 and third-party bundle configuration) must +be imported form inside this file in one way or another. This gives you absolute +flexibility over the services in your application. + +External service configuration can be imported in two different ways. First, +we'll talk about the method that you'll use most commonly in your application +- the ``imports`` directive. In the next section, we'll introduce the second +method, which is the flexible and preferred method for importing service +configuration from third-party bundles. + +.. index:: + single: Service Container; imports + +Importing Configuration with ``imports`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +So far, we've placed our ``my_mailer`` service container definition directly +in the application configuration file (e.g. ``app/config/config.yml``). Of +course, since the ``Mailer`` class itself lives inside ``HelloBundle``, it +makes more sense to put the ``my_mailer`` container definition inside the +bundle as well. + +First, move the ``my_mailer`` container definition into a new container resource +file in ``HelloBundle``. If the ``Resources`` or ``Resources/config`` directories +don't exist, create them. + +.. configuration-block:: + + .. code-block:: yaml + + # src/Sensio/HelloBundle/Resources/config/services.yml + parameters: + my_mailer.class: Sensio\HelloBundle\Mailer + my_mailer.transport: sendmail + + services: + my_mailer: + class: %my_mailer.class% + arguments: [%my_mailer.transport%] + + .. code-block:: xml + + + + Sensio\HelloBundle\Mailer + sendmailxml + + + + + %my_mailer.transport% + + + + .. code-block:: php + + // src/Sensio/HelloBundle/Resources/config/services.php + use Symfony\Component\DependencyInjection\Definition; + + $container->setParameter('my_mailer.class', 'Sensio\HelloBundle\Mailer'); + $container->setParameter('my_mailer.transport', 'sendmailphp'); + + $container->setDefinition('my_mailer', new Definition( + '%my_mailer.class%', + array('%my_mailer.transport%') + )); + +The definition itself hasn't changed, only its location. Of course the service +container doesn't know about the new resource file. Fortunately, we can +easily import the resource file using the ``imports`` key in the application +configuration. + +.. configuration-block:: + + .. code-block:: yaml + + imports: + hello_bundle: + resource: @HelloBundle/Resources/config/services.yml + + .. code-block:: xml + + + + + + .. code-block:: php + + $this->import('@HelloBundle/Resources/config/services.php'); + +The ``imports`` directive allows your application to include service container +configuration resources from any other location (most commonly from bundles). +The ``resource`` location, for files, is the absolute path to the resource +file. The special ``@HelloBundle`` syntax resolves to the directory path to +the ``HelloBundle``. This helps you specify the path to the resource without +worrying later if you move the ``HelloBundle`` to a different directory. + +.. index:: + single: Service Container; Extension configuration + +.. _`service-container-extension-configuration` + +Importing Configuration via Container Extensions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When developing in Symfony2, you'll most commonly use the ``imports`` directive +to import container configuration from the bundles in your project. Third +-party bundle container configuration (including the Symfony2 core services), +are usually loaded using another method that's more flexible, but easy to +configure in your application. + +Here's how it works. Internally, each bundle defines defines its services +very much like we've seen so far in this guide. Namely, the bundle uses one +or more configuration resource files (usually XML) to specify the parameters +and services for that bundle. However, instead of importing each of these +resources from your application configuration, you can simply invoke a *service +container extension* inside the bundle that does all the work for you. + +Take the ``FrameworkBundle`` - the core Symfony2 framework bundle - as an +example. The presence of the following code in your application configuration +invokes the service container extension inside the ``FrameworkBundle``:: + +.. configuration-block:: + + code-block:: yaml + + app.config: ~ + + code-block:: xml + + + + code-block:: php + + $container->loadFromExtension('app', 'config'); + +When the configuration is parsed, the container looks for an extension that +can handle the ``app.config`` configuration directive. The extension in question, +which lives in the ``FrameworkBundle`` is invoked and the service configuration +for the ``FrameworkBundle`` is loaded. If you remove the ``app.config`` key +from your application configuration file, the core Symfony2 services won't +be loaded. The point is that you're in control: the Symfony2 framework doesn't +doesn't perform any magic or perform any actions that you don't have control +over. + +Of course you can do much more than simply "activate" the service container +extension of the ``FrameworkBundle``. Each extension allows you to easily +customize the bundle, without worrying about how the internal services are +defined. In fact, the default configuration beneath ``app.config`` looks much +more like this: + +.. configuration-block:: + + .. code-block:: yaml + + app.config: + charset: UTF-8 + error_handler: null + csrf_protection: + enabled: true + secret: xxxxxxxxxx + router: { resource: "%kernel.root_dir%/config/routing.yml" } + # ... + + .. code-block:: xml + + + + + + + + .. code-block:: php + + $container->loadFromExtension('app', 'config', array( + 'charset' => 'UTF-8', + 'error_handler' => null, + 'csrf-protection' => array('enabled' => true, 'secret' => 'xxxxxxxxxx'), + 'router' => array('resource' => '%kernel.root_dir%/config/routing.php'), + // ... + )); + +In this case, the extension allows you to customize the ``charset``, ``error_handerl``, +``csrf_protection``, ``router`` configuration and much more. Internally, +the ``FrameworkBundle`` uses the options specified here to define and configure +the services specific to it. The bundle takes care of creating all the necessary +``parameters`` and ``services`` for the service container, while still allowing +much of the configuration to be easily customized. + +When installing or configuring a bundle, see the bundle's documentation for +how the services for the bundle should be installed and configured. The options +available for the core bundles can be found inside the :doc:`Reference Guide`. + +.. note:: + + By default, the service container only recognizes the ``parameters``, + ``services``, ``imports`` and ``interfaces`` directives. Any other directives + are handled by a service container extension. + +.. index:: + single: Service Container; Referencing services + +Referencing (Injecting) Services +-------------------------------- + +So far, our original ``my_mailer`` service is simple: it takes just one argument +in its constructor, which is easily configurable. As you'll see, the real +power of the container is realized when you need to create a service that +depends on one or more other services in the container. + +Let's start with an example. Suppose we have a new service, ``NewsletterManager``, +that helps to manage the preparating and delivery of an email message to +a collection of addresses. Of course the ``my_mailer`` service is already +really good at deliver email messages, so we'll use it inside ``NewsletterManager`` +to handle the actual delivery of the messages. This pretend class might look +something like this:: + + namespace Sensio\HelloBundle\Newsletter; + use Sensio\HelloBundle\Mailer; + + class NewsletterManager + { + protected $mailer; + + public function __construct(Mailer $mailer) + { + $this->mailer = $mailer; + } + + // ... + } + +Without using the service container, we can create a new ``NewsletterManager`` +fairly easily from inside a controller:: + + public function sendNewsletterAction() + { + $mailer = $this->container->get('my_mailer'); + $newsletter = new Sensio\HelloBundle\Newsletter\NewsletterManager($mailer); + // ... + } + +This approach is fine, but what if we decide later that the ``NewsletterManager`` +class needs a second or third constructor argument? What if we decide to +refactor our code and rename the class? In both cases, you'd need to find every +place where the ``NewsletterManager`` is instantiated and modify it. Of course, +the service container gives us a much more appealing option: + +.. configuration-block:: + + .. code-block:: yaml + + # src/Sensio/HelloBundle/Resources/config/services.yml + parameters: + # ... + newsletter_manager.class: Sensio\HelloBundle\Newsletter\NewsletterManager + + services: + my_mailer: + # ... + newsletter_manager: + class: %newsletter_manager.class% + arguments: [@my_mailer] + + .. code-block:: xml + + + + + Sensio\HelloBundle\Newsletter\NewsletterManager + + + + + + + + + + + + .. code-block:: php + + // src/Sensio/HelloBundle/Resources/config/services.php + use Symfony\Component\DependencyInjection\Definition; + + // ... + $container->setParameter('newsletter_manager.class', 'Sensio\HelloBundle\Newsletter\NewsletterManager'); + + $container->setDefinition('my_mailer', ... ); + $container->setDefinition('newsletter_manager', new Definition( + '%newsletter_manager.class%', + array(new Reference('my_mailer')) + )); + +In YAML, the special ``@my_mailer`` syntax tells the container to look for +a service named ``my_mailer`` and to pass that object into the constructor +of ``NewsletterManager``. + +This is a very powerful tool that allows you to create independent service +classes with well-defined dependencies. In this example, the ``newsletter_manager`` +service needs the ``my_mailer`` service in order to function. When you define +this dependency in the service container, the container takes care of all +the work of instantiating the objects. + +Core Symfony and Third-Party Bundle Services +-------------------------------------------- + +Since Symfony2 and all third-party bundles configure and retrieve their services +via the container, you can easily access them or even use them in your own +services. For example, to handle the storage of information on a user's +session, Symfony2 provides a ``session`` service:: + + public function indexAction($bar) + { + $session = $this->container->get('session'); + $session->set('foo', $bar); + + // ... + } + +In Symfony2, youll constantly use services provided by the Symfony core or +other third-party bundles to perform tasks such as rendering templates (``templating``), +sending emails (``mailer``), or accessing information on the request (``request``). + +We can take this a step further by using these services inside services that +you've created for your application. Let's modify the ``NewsletterManager`` +to use the real Symfony2 ``mailer`` service (instead of the pretend ``my_mailer``). +Let's also pass the templating engine service to the ``NewsletterManager`` +so that it can generate the email content via a template:: + + namespace Sensio\HelloBundle\Newsletter; + use Symfony\Component\Templating\EngineInterface; + + class NewsletterManager + { + protected $mailer; + + protected $templating; + + public function __construct(\Swift_Mailer $mailer, EngineInterface $templating) + { + $this->mailer = $mailer; + $this->templating = $templating; + } + + // ... + } + +Configuring the service container is easy: + +.. configuration-block:: + + .. code-block:: yaml + + services: + newsletter_manager: + class: %newsletter_manager.class% + arguments: [@mailer, @templating] + + .. code-block:: xml + + + + + + + .. code-block:: php + + $container->setDefinition('newsletter_manager', new Definition( + '%newsletter_manager.class%', + array( + new Reference('mailer'), + new Reference('templating') + ) + )); + +The ``newsletter_manager`` service now has access to the core ``mailer`` +and ``templating`` services. This is a common way to create services specific +to your application that leverage the power of different services within +the framework. + +.. tip:: + + Be sure that ``swift_mailer.config`` entry appears in your application + configuration. As we mentioned in :ref:`service-container-extension-configuration`, + the ``swift_mailer.config`` invokes the service configuration 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. + +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 +tagged. In the service container, a tag implies that the service is meant +to be used for a specific purpose. Take the following example: + +.. configuration-block:: + + .. code-block:: yaml + + services: + foo.twig.extension: + class: Sensio\HelloBundle\Extension\FooExtension + tags: + twig.extension: + name: twig.extension + + .. code-block:: xml + + + + + + .. code-block:: php + + $definition = new Definition('Sensio\HelloBundle\Extension\RadiusExtension'); + $definition->addTag('twig.extension'); + $container->setDefinition('foo.twig.extension', $definition); + +The ``twig.extension`` tag is a special tag that the ``TwigBundle`` uses +during configuration. By giving the service this ``twig.extension`` tag, +the bundle knows that the ``foo.twig.extension`` service should be registered +as a Twig extension with Twig. In other words, Twig finds all services tagged +with ``twig.extension`` and automatically registers them as extensions. + +Tags, then, are a way to tell Symfony2 or other third-party bundles that +your service should be registered or used in some specialy way by the bundle. + +The following is a list of the tags available with the core Symfony2 bundles. +Each of these has a different affect on your service and many tags require +additional arguments (beyond just the tag ``name``). + +* assetic.filter +* assetic.templating.php +* data_collector +* form.field_factory.guesser +* kernel.cache_warmer +* kernel.listener +* routing.loader +* security.listener.factory +* security.voter +* templating.helper +* twig.extension +* translation.loader +* validator.constraint_validator +* zend.logger.writer + +.. _`service-oriented architecture`: http://wikipedia.org/wiki/Service-oriented_architecture \ No newline at end of file From ca5ca36fda35bd49c5cf42f26a1b5eed049b5b98 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sun, 13 Feb 2011 08:47:18 -0600 Subject: [PATCH 2/7] [reference] Bootstrapping the reference section. --- index.rst | 12 ++++++++++++ reference/index.rst | 6 ++++++ reference/map.rst.inc | 13 +++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 reference/index.rst create mode 100644 reference/map.rst.inc diff --git a/index.rst b/index.rst index 2a5d6603587..634f9e6a8ee 100644 --- a/index.rst +++ b/index.rst @@ -28,6 +28,18 @@ Dive into Symfony2 with the topical guides: .. include:: guides/map.rst.inc +Reference Documents +------------------- + +Get answers quickly with reference documents: + +.. toctree:: + :hidden: + + reference/index + +.. include:: reference/map.rst.inc + Contributing ------------ diff --git a/reference/index.rst b/reference/index.rst new file mode 100644 index 00000000000..63f285a9739 --- /dev/null +++ b/reference/index.rst @@ -0,0 +1,6 @@ +Reference Documents +=================== + +Get answers quickly with reference documents: + +.. include:: map.rst.inc diff --git a/reference/map.rst.inc b/reference/map.rst.inc new file mode 100644 index 00000000000..2245a7e298a --- /dev/null +++ b/reference/map.rst.inc @@ -0,0 +1,13 @@ +* **Bundle Configuration**: + + * :doc:`FrameworkBundle (app.config) ` | + * :doc:`DoctrineBundle (doctrine.*) ` | + * :doc:`DoctrineMongoDBBundle (doctrine_odm.mongodb) ` | + * :doc:`SecurityBundle (security.*) ` | + * :doc:`FrameworkBundle (swiftmailer.config) ` | + * :doc:`TwigBundle (twig.config) ` | + * :doc:`WebProfilerBundle (webprofiler.config) ` | + * :doc:`ZendBundle (zend.config) ` + +* :doc:`/guides/forms/fields/index` +* :doc:`/guides/validator/constraints/index` From a4a71c3f40e269e1f370489563a7fa761df1a8ce Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sun, 13 Feb 2011 21:29:56 -0600 Subject: [PATCH 3/7] [service_container] Renaming everything to "Service Container", which is a less-scary name and more descriptive. Also proofreading. --- glossary.rst | 4 +- guides/index.rst | 1 + guides/internals/overview.rst | 2 +- guides/map.rst.inc | 5 +- .../index.rst} | 107 ++++++++++-------- reference/map.rst.inc | 2 +- 6 files changed, 68 insertions(+), 53 deletions(-) rename guides/{service_container.rst => service_container/index.rst} (88%) diff --git a/glossary.rst b/glossary.rst index 8a1492770c8..7599dd9771a 100644 --- a/glossary.rst +++ b/glossary.rst @@ -36,7 +36,7 @@ Glossary is a special object that manages the instantiation of services inside an application. Instead of creating services directly, the developer *trains* the service container (via configuration) on how to create - the services. The service container eases takes care of lazily instantiating + the services. The service container takes care of lazily instantiating and injecting dependent services. -.. _`service-oriented architecture`: http://wikipedia.org/wiki/Service-oriented_architecture \ No newline at end of file +.. _`service-oriented architecture`: http://wikipedia.org/wiki/Service-oriented_architecture diff --git a/guides/index.rst b/guides/index.rst index b398d1a9767..9f69c20d385 100644 --- a/guides/index.rst +++ b/guides/index.rst @@ -18,6 +18,7 @@ Dive into Symfony2 with the topical guides: event/index tools/index bundles/index + service_container/index internals/index symfony1 stable_api diff --git a/guides/internals/overview.rst b/guides/internals/overview.rst index 0d94b9edcd1..f087190a878 100644 --- a/guides/internals/overview.rst +++ b/guides/internals/overview.rst @@ -62,7 +62,7 @@ Dependency Injection component and a powerful plugin system (bundles). .. seealso:: Read more about the :doc:`HttpKernel ` component. Read more about - :doc:`Dependency Injection ` and + :doc:`Dependency Injection ` and :doc:`Bundles `. ``FrameworkBundle`` Bundle diff --git a/guides/map.rst.inc b/guides/map.rst.inc index fd47397d330..7eb0f6cc944 100644 --- a/guides/map.rst.inc +++ b/guides/map.rst.inc @@ -64,9 +64,10 @@ * :doc:`Best Practices ` | * :doc:`Configuration ` -* **Dependency Injection**: +* **Service Container**: - * :doc:`Extensions ` + * :doc:`Service Container ` + * :doc:`Extensions ` * **Internals**: diff --git a/guides/service_container.rst b/guides/service_container/index.rst similarity index 88% rename from guides/service_container.rst rename to guides/service_container/index.rst index 5e9e77df30e..8f0fc77a4cb 100644 --- a/guides/service_container.rst +++ b/guides/service_container/index.rst @@ -10,17 +10,17 @@ delivery of email messages while another may allow you to persist information into a database. In your application, you may create an object that manages your product inventory, or another object that processes data from a third-party API. The point is that a modern application does many things and is organized -into many object that handle each task. +into many objects that handle each task. In this guide, we'll talk about a special PHP object in Symfony2 that helps -your instantiate, organize and retrieve the many object of your application. +your instantiate, organize and retrieve the many objects of your application. This object, called a service container, will allow you to standardize and centralize the way objects are constructed in your application. The container -makes your life easier, is super fast, and emphasizes and architecture that +makes your life easier, is super fast, and emphasizes an architecture that promotes reusable and decoupled code. And since all core Symfony2 classes use the container, you'll learn how to extend, configure and use any object in Symfony2. In large part, the service container is the biggest contributor -to the speed and extensability of Symfony2. +to the speed and extensibility of Symfony2. Finally, configuring and using the service container is easy. By the end of this chapter, you'll be comfortable creating your own objects via the @@ -37,8 +37,8 @@ What is a Service? Put simply, a :term:`Service` is any PHP object that does something. It's a purposefully-generic name used in computer science to describe an object that's created for a specific purpose (e.g. delivering emails). You don't -have to do anything specialy to make a service: simply write a PHP class -with some code that accomplishes a specific task. Congrtulations, you've +have to do anything special to make a service: simply write a PHP class +with some code that accomplishes a specific task. Congratulations, you've just created a service! So what's the big deal then? The advantage of thinking about "services" is @@ -49,7 +49,7 @@ need it. Each service can also be more easily tested and configured since it's separated from the other functionality in your application. This idea is called `service-oriented architecture`_ and is not unique to Symfony2 or even PHP. Structuring your application around a set of independent service -classes is well-known and trusted object-oriented best-practice. These skills +classes is a well-known and trusted object-oriented best-practice. These skills are key to being a good developer in almost any language. .. index:: @@ -64,7 +64,7 @@ For example, suppose we have a simple PHP class that delivers email messages. Without a service container, we must manually create the object whenever we need it: -.. code-block:: +.. code-block:: php use Sensio\HelloBundle\Mailer; @@ -123,7 +123,7 @@ be specified in YAML, XML or PHP: When Symfony2 initializes, it builds the service container using the application configuration (``app/config/config.yml`` by default). The - exact file that's loaded is dicated by the ``AppKernel::loadConfig()`` + exact file that's loaded is dictated by the ``AppKernel::loadConfig()`` method, which loads an environment-specific configuration file (e.g. ``config_dev.yml`` for the ``dev`` environment or ``config_prod.yml`` for ``prod``). @@ -146,7 +146,7 @@ Symfony2 controller, we can easily access the new ``my_mailer`` service:: .. tip:: - When using a tranditional controller, there's an even shorter way to + When using a traditional controller, there's an even shorter way to access a service from the container. This is exactly equivalent to the above method, but with less keystrokes:: @@ -155,7 +155,7 @@ Symfony2 controller, we can easily access the new ``my_mailer`` service:: When we ask for the ``my_mailer`` service from the container, the container constructs the object and returns it. This is another major advantage of using the service container. Namely, a service is *never* constructed until -its needed. If you define a service and never use it on a request, the service +it's needed. If you define a service and never use it on a request, the service is never created. This saves memory and increases the speed of your application. This also means that there's very little or no performance hit for defining lot's of services. Services that are never used are never constructed. @@ -190,7 +190,7 @@ straightforward. Parameters make defining services more organized and flexible: Sensio\HelloBundle\Mailer - sendmailxml + sendmail @@ -205,7 +205,7 @@ straightforward. Parameters make defining services more organized and flexible: use Symfony\Component\DependencyInjection\Definition; $container->setParameter('my_mailer.class', 'Sensio\HelloBundle\Mailer'); - $container->setParameter('my_mailer.transport', 'sendmailphp'); + $container->setParameter('my_mailer.transport', 'sendmail'); $container->setDefinition('my_mailer', new Definition( '%my_mailer.class%', @@ -228,7 +228,7 @@ Parameters, however, have several advantages: * parameter values can be used in multiple service definitions; * when creating a service in a bundle (we'll show this shortly), using parameters - allows the service to be easily customized in your application; + allows the service to be easily customized in your application. The choice of using or not using parameters is up to you. High-quality third-party bundles will *always* use parameters as they make the service @@ -254,8 +254,8 @@ flexibility over the services in your application. External service configuration can be imported in two different ways. First, we'll talk about the method that you'll use most commonly in your application -- the ``imports`` directive. In the next section, we'll introduce the second -method, which is the flexible and preferred method for importing service +- the ``imports`` directive. In the following section, we'll introduce the +second method, which is the flexible and preferred method for importing service configuration from third-party bundles. .. index:: @@ -293,7 +293,7 @@ don't exist, create them. Sensio\HelloBundle\Mailer - sendmailxml + sendmail @@ -308,7 +308,7 @@ don't exist, create them. use Symfony\Component\DependencyInjection\Definition; $container->setParameter('my_mailer.class', 'Sensio\HelloBundle\Mailer'); - $container->setParameter('my_mailer.transport', 'sendmailphp'); + $container->setParameter('my_mailer.transport', 'sendmail'); $container->setDefinition('my_mailer', new Definition( '%my_mailer.class%', @@ -324,18 +324,21 @@ configuration. .. code-block:: yaml + # app/config/config.yml imports: hello_bundle: resource: @HelloBundle/Resources/config/services.yml .. code-block:: xml + .. code-block:: php + // app/config/config.php $this->import('@HelloBundle/Resources/config/services.php'); The ``imports`` directive allows your application to include service container @@ -348,50 +351,55 @@ worrying later if you move the ``HelloBundle`` to a different directory. .. index:: single: Service Container; Extension configuration -.. _`service-container-extension-configuration` +.. _service-container-extension-configuration: Importing Configuration via Container Extensions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ When developing in Symfony2, you'll most commonly use the ``imports`` directive -to import container configuration from the bundles in your project. Third --party bundle container configuration (including the Symfony2 core services), -are usually loaded using another method that's more flexible, but easy to -configure in your application. - -Here's how it works. Internally, each bundle defines defines its services -very much like we've seen so far in this guide. Namely, the bundle uses one -or more configuration resource files (usually XML) to specify the parameters -and services for that bundle. However, instead of importing each of these -resources from your application configuration, you can simply invoke a *service -container extension* inside the bundle that does all the work for you. +to import container configuration from the bundles you've created specifically +for your application. Third-party bundle container configuration (including +the Symfony2 core services), are usually loaded using another method that's +more flexible and easy to configure in your application. + +Here's how it works. Internally, each bundle defines its services very much +like we've seen so far in this guide. Namely, a bundle uses one or more +configuration resource files (usually XML) to specify the parameters and +services for that bundle. However, instead of importing each of these resources +directly from your application configuration using the ``imports`` directive, +you can simply invoke a *service container extension* inside the bundle that +does all the work for you. A service container extension is a PHP class created +by the bundle author to take care of all the service container configuration +on your behalf. Take the ``FrameworkBundle`` - the core Symfony2 framework bundle - as an example. The presence of the following code in your application configuration -invokes the service container extension inside the ``FrameworkBundle``:: +invokes the service container extension inside the ``FrameworkBundle``: .. configuration-block:: - code-block:: yaml + .. code-block:: yaml + # app/config/config.yml app.config: ~ - code-block:: xml + .. code-block:: xml + - code-block:: php + .. code-block:: php + // app/config/config.php $container->loadFromExtension('app', 'config'); When the configuration is parsed, the container looks for an extension that can handle the ``app.config`` configuration directive. The extension in question, -which lives in the ``FrameworkBundle`` is invoked and the service configuration +which lives in the ``FrameworkBundle``, is invoked and the service configuration for the ``FrameworkBundle`` is loaded. If you remove the ``app.config`` key from your application configuration file, the core Symfony2 services won't be loaded. The point is that you're in control: the Symfony2 framework doesn't -doesn't perform any magic or perform any actions that you don't have control -over. +contain any magic or perform any actions that you don't have control over. Of course you can do much more than simply "activate" the service container extension of the ``FrameworkBundle``. Each extension allows you to easily @@ -403,6 +411,7 @@ more like this: .. code-block:: yaml + # app/config/config.yml app.config: charset: UTF-8 error_handler: null @@ -414,6 +423,7 @@ more like this: .. code-block:: xml + @@ -422,6 +432,7 @@ more like this: .. code-block:: php + // app/config/config.php $container->loadFromExtension('app', 'config', array( 'charset' => 'UTF-8', 'error_handler' => null, @@ -430,12 +441,14 @@ more like this: // ... )); -In this case, the extension allows you to customize the ``charset``, ``error_handerl``, +In this case, the extension allows you to customize the ``charset``, ``error_handler``, ``csrf_protection``, ``router`` configuration and much more. Internally, the ``FrameworkBundle`` uses the options specified here to define and configure the services specific to it. The bundle takes care of creating all the necessary ``parameters`` and ``services`` for the service container, while still allowing -much of the configuration to be easily customized. +much of the configuration to be easily customized. As an added bonus, most +service container extensions are also smart enough to perform validation - +notifying you of missing options or options with the wrong data type. When installing or configuring a bundle, see the bundle's documentation for how the services for the bundle should be installed and configured. The options @@ -443,7 +456,7 @@ available for the core bundles can be found inside the :doc:`Reference Guide` | * :doc:`DoctrineBundle (doctrine.*) ` | * :doc:`DoctrineMongoDBBundle (doctrine_odm.mongodb) ` | - * :doc:`SecurityBundle (security.*) ` | + * :doc:`SecurityBundle (security.*) ` | * :doc:`FrameworkBundle (swiftmailer.config) ` | * :doc:`TwigBundle (twig.config) ` | * :doc:`WebProfilerBundle (webprofiler.config) ` | From f0ef5f6e99404513c4a197c0d1982c8074d39c96 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Mon, 14 Feb 2011 08:28:59 -0600 Subject: [PATCH 4/7] [service_container] Fixing typo per Stof. --- guides/service_container/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guides/service_container/index.rst b/guides/service_container/index.rst index 8f0fc77a4cb..169e94a499a 100644 --- a/guides/service_container/index.rst +++ b/guides/service_container/index.rst @@ -249,7 +249,7 @@ Importing other Container Configuration Resources The service container is built using a single configuration resource (``app/config/config.yml`` by default). All other service configuration( (including the core Symfony2 and third-party bundle configuration) must -be imported form inside this file in one way or another. This gives you absolute +be imported from inside this file in one way or another. This gives you absolute flexibility over the services in your application. External service configuration can be imported in two different ways. First, From b95b039ff8e51bcb2b42be0d8e6d15c184ade7dc Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 15 Feb 2011 07:04:08 -0600 Subject: [PATCH 5/7] [service_container] Renaming service container to DIC, fixing several typos and making a few other changes: * Adding more information on what makes a PHP object a service and more on the DIC exension providing semantic configuration for the bundle. * Reworking the docs so that I don't show an empty ``app.config``. --- .../index.rst | 92 ++++++++++--------- guides/index.rst | 2 +- guides/internals/overview.rst | 2 +- guides/map.rst.inc | 6 +- 4 files changed, 52 insertions(+), 50 deletions(-) rename guides/{service_container => dependency_injection}/index.rst (92%) diff --git a/guides/service_container/index.rst b/guides/dependency_injection/index.rst similarity index 92% rename from guides/service_container/index.rst rename to guides/dependency_injection/index.rst index 169e94a499a..1cf1a7bdefb 100644 --- a/guides/service_container/index.rst +++ b/guides/dependency_injection/index.rst @@ -13,7 +13,7 @@ API. The point is that a modern application does many things and is organized into many objects that handle each task. In this guide, we'll talk about a special PHP object in Symfony2 that helps -your instantiate, organize and retrieve the many objects of your application. +you instantiate, organize and retrieve the many objects of your application. This object, called a service container, will allow you to standardize and centralize the way objects are constructed in your application. The container makes your life easier, is super fast, and emphasizes an architecture that @@ -34,12 +34,21 @@ the service container makes writing good code so easy. What is a Service? ------------------ -Put simply, a :term:`Service` is any PHP object that does something. It's -a purposefully-generic name used in computer science to describe an object -that's created for a specific purpose (e.g. delivering emails). You don't -have to do anything special to make a service: simply write a PHP class -with some code that accomplishes a specific task. Congratulations, you've -just created a service! +Put simply, a :term:`Service` is any PHP object that performs some sort of +"global" task. It's a purposefully-generic name used in computer science +to describe an object that's created for a specific purpose (e.g. delivering +emails). Each service is used throughout your application whenever you need +the specific functionality it provides. You don't have to do anything special +to make a service: simply write a PHP class with some code that accomplishes +a specific task. Congratulations, you've just created a service! + +.. note:: + + As a rule, a PHP object is a service if it is used globally in your + application. A single ``Mailer`` service is used globally to send + email messages whereas the many ``Message`` objects that it delivers + are *not* services. Similarly, a ``Product`` object is not a service, + but an object that persists ``Product`` objects to a database *is* a service. So what's the big deal then? The advantage of thinking about "services" is that you begin to think about separating each piece of functionality in your @@ -158,7 +167,7 @@ using the service container. Namely, a service is *never* constructed until it's needed. If you define a service and never use it on a request, the service is never created. This saves memory and increases the speed of your application. This also means that there's very little or no performance hit for defining -lot's of services. Services that are never used are never constructed. +lots of services. Services that are never used are never constructed. As an added bonus, the ``Mailer`` service is only created once and the same instance is returned each time you ask for the service. This is almost always @@ -247,7 +256,7 @@ Importing other Container Configuration Resources web service). The service container is built using a single configuration resource -(``app/config/config.yml`` by default). All other service configuration( +(``app/config/config.yml`` by default). All other service configuration (including the core Symfony2 and third-party bundle configuration) must be imported from inside this file in one way or another. This gives you absolute flexibility over the services in your application. @@ -368,44 +377,23 @@ configuration resource files (usually XML) to specify the parameters and services for that bundle. However, instead of importing each of these resources directly from your application configuration using the ``imports`` directive, you can simply invoke a *service container extension* inside the bundle that -does all the work for you. A service container extension is a PHP class created -by the bundle author to take care of all the service container configuration -on your behalf. - -Take the ``FrameworkBundle`` - the core Symfony2 framework bundle - as an -example. The presence of the following code in your application configuration -invokes the service container extension inside the ``FrameworkBundle``: +does the work for you. A service container extension is a PHP class created +by the bundle author to accomplish two things: -.. configuration-block:: - - .. code-block:: yaml +* import all of the service container resources needed to configure the + services for the bundle; - # app/config/config.yml - app.config: ~ - - .. code-block:: xml - - - - - .. code-block:: php - - // app/config/config.php - $container->loadFromExtension('app', 'config'); +* provide semantic, straightforward configuration so that the bundle can + be configured without interacting with the flat parameters of the bundle's + service container configuration. -When the configuration is parsed, the container looks for an extension that -can handle the ``app.config`` configuration directive. The extension in question, -which lives in the ``FrameworkBundle``, is invoked and the service configuration -for the ``FrameworkBundle`` is loaded. If you remove the ``app.config`` key -from your application configuration file, the core Symfony2 services won't -be loaded. The point is that you're in control: the Symfony2 framework doesn't -contain any magic or perform any actions that you don't have control over. +In other words, a service container extension configures the services for +a bundle on your behalf. And as we'll see in a moment, the extension provides +a sensible, high-level interface for configuring the bundle. -Of course you can do much more than simply "activate" the service container -extension of the ``FrameworkBundle``. Each extension allows you to easily -customize the bundle, without worrying about how the internal services are -defined. In fact, the default configuration beneath ``app.config`` looks much -more like this: +Take the ``FrameworkBundle`` - the core Symfony2 framework bundle - as an +example. The presence of the following code in your application configuration +invokes the service container extension inside the ``FrameworkBundle``: .. configuration-block:: @@ -441,6 +429,20 @@ more like this: // ... )); +When the configuration is parsed, the container looks for an extension that +can handle the ``app.config`` configuration directive. The extension in question, +which lives in the ``FrameworkBundle``, is invoked and the service configuration +for the ``FrameworkBundle`` is loaded. If you remove the ``app.config`` key +from your application configuration file entirely, the core Symfony2 services +won't be loaded. The point is that you're in control: the Symfony2 framework +doesn't contain any magic or perform any actions that you don't have control +over. + +Of course you can do much more than simply "activate" the service container +extension of the ``FrameworkBundle``. Each extension allows you to easily +customize the bundle, without worrying about how the internal services are +defined. + In this case, the extension allows you to customize the ``charset``, ``error_handler``, ``csrf_protection``, ``router`` configuration and much more. Internally, the ``FrameworkBundle`` uses the options specified here to define and configure @@ -645,9 +647,9 @@ the framework. .. tip:: - Be sure that ``swift_mailer.config`` entry appears in your application + Be sure that ``swiftmailer.config`` entry appears in your application configuration. As we mentioned in :ref:`service-container-extension-configuration`, - the ``swift_mailer.config`` invokes the service extension from the + the ``swiftmailer.config`` invokes the service extension from the ``SwiftmailerBundle``, which registers the ``mailer`` service. .. index:: diff --git a/guides/index.rst b/guides/index.rst index 9f69c20d385..72cff37d41a 100644 --- a/guides/index.rst +++ b/guides/index.rst @@ -18,7 +18,7 @@ Dive into Symfony2 with the topical guides: event/index tools/index bundles/index - service_container/index + dependency_injection/index internals/index symfony1 stable_api diff --git a/guides/internals/overview.rst b/guides/internals/overview.rst index f087190a878..0d94b9edcd1 100644 --- a/guides/internals/overview.rst +++ b/guides/internals/overview.rst @@ -62,7 +62,7 @@ Dependency Injection component and a powerful plugin system (bundles). .. seealso:: Read more about the :doc:`HttpKernel ` component. Read more about - :doc:`Dependency Injection ` and + :doc:`Dependency Injection ` and :doc:`Bundles `. ``FrameworkBundle`` Bundle diff --git a/guides/map.rst.inc b/guides/map.rst.inc index 7eb0f6cc944..7163279b043 100644 --- a/guides/map.rst.inc +++ b/guides/map.rst.inc @@ -64,10 +64,10 @@ * :doc:`Best Practices ` | * :doc:`Configuration ` -* **Service Container**: +* **Dependency Injection**: - * :doc:`Service Container ` - * :doc:`Extensions ` + * :doc:`The Service Container ` + * :doc:`Extensions ` * **Internals**: From 09e5f55d368f45603312163d733c4eb610d67138 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 15 Feb 2011 07:22:56 -0600 Subject: [PATCH 6/7] [glossary] Adding note to about *Services* to better distinguish them from other objects. --- glossary.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/glossary.rst b/glossary.rst index 7599dd9771a..728ed20b1d7 100644 --- a/glossary.rst +++ b/glossary.rst @@ -27,9 +27,11 @@ Glossary Service A *Service* is a generic term for any PHP object that performs a - specific task. In Symfony2, services are often configured and retrieved - from the service container. An application that has many decoupled - services is said to follow a `service-oriented architecture`_ + specific task. A service is usually used "globally", such as a database + connection object or an object that delivers email messages. In Symfony2, + services are often configured and retrieved from the service container. + An application that has many decoupled services is said to follow + a `service-oriented architecture`_ Service Container A *Service Container*, also known as a *Dependency Injection Container*, From 47fd408dbb82cd190d2b001a26bbab71ffebccea Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 17 Feb 2011 08:48:24 -0600 Subject: [PATCH 7/7] [dependency_injection] Updating the extension documentation for the latest changes. --- guides/dependency_injection/index.rst | 16 ++++++++-------- reference/map.rst.inc | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/guides/dependency_injection/index.rst b/guides/dependency_injection/index.rst index 1cf1a7bdefb..cefc4118562 100644 --- a/guides/dependency_injection/index.rst +++ b/guides/dependency_injection/index.rst @@ -400,7 +400,7 @@ invokes the service container extension inside the ``FrameworkBundle``: .. code-block:: yaml # app/config/config.yml - app.config: + framework: charset: UTF-8 error_handler: null csrf_protection: @@ -412,16 +412,16 @@ invokes the service container extension inside the ``FrameworkBundle``: .. code-block:: xml - + - + .. code-block:: php // app/config/config.php - $container->loadFromExtension('app', 'config', array( + $container->loadFromExtension('framework', array( 'charset' => 'UTF-8', 'error_handler' => null, 'csrf-protection' => array('enabled' => true, 'secret' => 'xxxxxxxxxx'), @@ -430,9 +430,9 @@ invokes the service container extension inside the ``FrameworkBundle``: )); When the configuration is parsed, the container looks for an extension that -can handle the ``app.config`` configuration directive. The extension in question, +can handle the ``framework`` configuration directive. The extension in question, which lives in the ``FrameworkBundle``, is invoked and the service configuration -for the ``FrameworkBundle`` is loaded. If you remove the ``app.config`` key +for the ``FrameworkBundle`` is loaded. If you remove the ``framework`` key from your application configuration file entirely, the core Symfony2 services won't be loaded. The point is that you're in control: the Symfony2 framework doesn't contain any magic or perform any actions that you don't have control @@ -647,9 +647,9 @@ the framework. .. tip:: - Be sure that ``swiftmailer.config`` entry appears in your application + Be sure that ``swiftmailer`` entry appears in your application configuration. As we mentioned in :ref:`service-container-extension-configuration`, - the ``swiftmailer.config`` invokes the service extension from the + the ``swiftmailer`` invokes the service extension from the ``SwiftmailerBundle``, which registers the ``mailer`` service. .. index:: diff --git a/reference/map.rst.inc b/reference/map.rst.inc index 2c18c4d22bc..e1a00703302 100644 --- a/reference/map.rst.inc +++ b/reference/map.rst.inc @@ -1,13 +1,13 @@ * **Bundle Configuration**: - * :doc:`FrameworkBundle (app.config) ` | - * :doc:`DoctrineBundle (doctrine.*) ` | - * :doc:`DoctrineMongoDBBundle (doctrine_odm.mongodb) ` | - * :doc:`SecurityBundle (security.*) ` | - * :doc:`FrameworkBundle (swiftmailer.config) ` | - * :doc:`TwigBundle (twig.config) ` | - * :doc:`WebProfilerBundle (webprofiler.config) ` | - * :doc:`ZendBundle (zend.config) ` + * :doc:`FrameworkBundle (framework) ` | + * :doc:`DoctrineBundle (doctrine) ` | + * :doc:`DoctrineMongoDBBundle (doctrine_mongo_db) ` | + * :doc:`SecurityBundle (security) ` | + * :doc:`FrameworkBundle (swiftmailer) ` | + * :doc:`TwigBundle (twig) ` | + * :doc:`WebProfilerBundle (web_profiler) ` | + * :doc:`ZendBundle (zend) ` * :doc:`/guides/forms/fields/index` * :doc:`/guides/validator/constraints/index`