Skip to content

update cookbook for couch and phpcr and give some more hints and background #2668

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

Closed
wants to merge 11 commits into from
6 changes: 3 additions & 3 deletions components/console/helpers/tablehelper.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ You can also control table rendering by setting custom rendering option values:
* :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setPaddingChar`
* :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setHorizontalBorderChar`
* :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setVerticalBorderChar`
* :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setVrossingChar`
* :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setVellHeaderFormat`
* :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setVellRowFormat`
* :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setCrossingChar`
* :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setCellHeaderFormat`
* :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setCellRowFormat`
* :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setBorderFormat`
* :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setPadType`
1 change: 1 addition & 0 deletions components/dependency_injection/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@
configurators
parentservices
advanced
lazy_services
workflow

92 changes: 92 additions & 0 deletions components/dependency_injection/lazy_services.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
.. index::
single: Dependency Injection; Lazy Services

Lazy Services
=============

.. versionadded:: 2.3
Lazy services were added in Symfony 2.3.

Why Lazy Services?
------------------

In some cases, you may want to inject a service that is a bit heavy to instantiate,
but is not always used inside your object. For example, imagine you have
a ``NewsletterManager`` and you inject a ``mailer`` service into it. Only
a few methods on your ``NewsletterManager`` actually use the ``mailer``,
but even when you don't need it, a ``mailer`` service is always instantiated
in order to construct your ``NewsletterManager``.

Configuring lazy services is one answer to this. With a lazy service, a "proxy"
of the ``mailer`` service is actually injected. It looks and acts just like
the ``mailer``, except that the ``mailer`` isn't actually instantiated until
you interact with the proxy in some way.

Installation
------------

In order to use the lazy service instantiation, you will first need to install
the `ProxyManager bridge`_:

.. code-block:: bash

$ php composer.phar require symfony/proxy-manager-bridge:2.3.*

.. note::

If you're using the full-stack framework, this package is not included
and needs to be added to ``composer.json`` and installed (which is what
the above command does).

Configuration
-------------

You can mark the service as ``lazy`` by manipulating its definition:

.. configuration-block::

.. code-block:: yaml

services:
foo:
class: Acme\Foo
lazy: true

.. code-block:: xml

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

.. code-block:: php

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

You can then require the service from the container::

$service = $container->get('foo');

At this point the retrieved ``$service`` should be a virtual `proxy`_ with
the same signature of the class representing the service. You can also inject
the service just like normal into other services. The object that's actually
injected will be the proxy.

.. note::

If you don't install the `ProxyManager bridge`_, the container will just
skip over the ``lazy`` flag and simply instantiate the service as it would
normally do.

The proxy gets initialized and the actual service is instantiated as soon
as you interact in any way with this object.

Additional Resources
--------------------

You can read more about how proxies are instantiated, generated and initialized
in the `documentation of ProxyManager`_.


.. _`ProxyManager bridge`: https://github.com/symfony/symfony/tree/master/src/Symfony/Bridge/ProxyManager
.. _`proxy`: http://en.wikipedia.org/wiki/Proxy_pattern
.. _`documentation of ProxyManager`: https://github.com/Ocramius/ProxyManager/blob/master/docs/lazy-loading-value-holder.md
2 changes: 1 addition & 1 deletion components/intl.rst
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ expose them manually by adding the following lines to your autoload code::
but usually Composer does this for you automatically:

* 1.0.*: when the intl extension is not available
* 1.1.*: when intl is compiled with ICU 4.0 or higher
* 1.1.*: when intl is compiled with ICU 3.8 or higher
* 1.2.*: when intl is compiled with ICU 4.4 or higher

These versions are important when you deploy your application to a **server with
Expand Down
1 change: 1 addition & 0 deletions components/map.rst.inc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
* :doc:`/components/dependency_injection/configurators`
* :doc:`/components/dependency_injection/parentservices`
* :doc:`/components/dependency_injection/advanced`
* :doc:`/components/dependency_injection/lazy_services`
* :doc:`/components/dependency_injection/workflow`

* **DOM Crawler**
Expand Down
76 changes: 71 additions & 5 deletions cookbook/doctrine/mapping_model_classes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,25 @@ register the mappings for your model classes.
just to get the auto mapping, use the compiler pass.

.. versionadded:: 2.3

The base mapping compiler pass was added in Symfony 2.3. The doctrine bundles
support it from DoctrineBundle >= 1.2.1, MongoDBBundle >= 3.0.0
support it from DoctrineBundle >= 1.2.1, MongoDBBundle >= 3.0.0,
PHPCRBundle >= 1.0.0-alpha2 and the (unversioned) CouchDBBundle supports the
compiler pass since the `CouchDB Mapping Compiler Pass pull request`_
was merged.

If you want your bundle to support older versions of Symfony and
Doctrine, you can provide a copy of the compiler pass in your bundle.
See for example the `FOSUserBundle mapping configuration`_
``addRegisterMappingsPass``.


In your bundle class, write the following code to register the compiler pass::

use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\DoctrineOrmMappingsPass;
use Doctrine\Bundle\MongoDBBundle\DependencyInjection\Compiler\DoctrineMongoDBMappingsPass;
use Doctrine\Bundle\CouchDBBundle\DependencyInjection\Compiler\DoctrineCouchDBMappingsPass;
use Doctrine\Bundle\PHPCRBundle\DependencyInjection\Compiler\DoctrinePhpcrMappingsPass;

class FOSUserBundle extends Bundle
{
Expand Down Expand Up @@ -55,10 +67,64 @@ In your bundle class, write the following code to register the compiler pass::
));
}

// TODO: couch
$couchCompilerClass = 'Doctrine\Bundle\CouchDBBundle\DependencyInjection'
. '\Compiler\DoctrineCouchDBMappingsPass';
if (class_exists($couchCompilerClass)) {
$container->addCompilerPass(
DoctrinCouchDBMappingsPass::createXmlMappingDriver(
$mappings, 'fos_user.backend_type_couchdb'
));
}

$phpcrCompilerClass = 'Doctrine\Bundle\PHPCRBundle\DependencyInjection'
. '\Compiler\DoctrinePhpcrMappingsPass';
if (class_exists($phpcrCompilerClass)) {
$container->addCompilerPass(
DoctrinePhpcrMappingsPass::createXmlMappingDriver(
$mappings, 'fos_user.backend_type_phpcr'
));
}
}
}

The compiler pass provides factory methods for all drivers provided by the
bundle: Annotations, XML, Yaml, PHP and StaticPHP for Doctrine ORM, the ODM
bundles sometimes do not have all of those drivers.
Note the ``class_exists`` check. This is crucial, as you do not want your
bundle to have a hard dependency on all doctrine bundles but let the user
decide which to use.

The compiler pass provides factory methods for all drivers provided by doctrine:
Annotations, XML, Yaml, PHP and StaticPHP. The arguments are

* a map of absolute directory path to namespace;
* an array of container parameters that your bundle uses to specify the name of
the doctrine manager that it is using. The compiler pass will append the
parameter doctrine is using to specify the name of the default manager. The
first parameter found is used and the mappings are registered with that
manager;
* an optional container parameter name that will be used by the compiler
pass to determine if this doctrine type is used at all (this is relevant if
your user has more than one type of doctrine bundle installed, but your
bundle is only used with one type of doctrine.

.. note::

The factory method is using the ``SymfonyFileLocator`` of doctrine, meaning
it will only see XML and YML mapping files if they do not contain the
namespace. If you also need to map a base class, you can register a
compiler pass with the ``DefaultFileLocator`` like this::

private function buildMappingCompilerPass()
{
$arguments = array(array(realpath(__DIR__ . '/Resources/config/doctrine')), '.orm.xml');
$locator = new Definition('Doctrine\Common\Persistence\Mapping\Driver\DefaultFileLocator', $arguments);
$driver = new Definition('Doctrine\ORM\Mapping\Driver\XmlDriver', array($locator));

return new DoctrineOrmMappingsPass(
$driver,
array('Full\Namespace'),
array('your_bundle.manager_name'),
'your_bundle.orm_enabled'
);
}

.. _`CouchDB Mapping Compiler Pass pull request`: https://github.com/doctrine/DoctrineCouchDBBundle/pull/27
.. _`FOSUserBundle mapping configuration`: https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/FOSUserBundle.php