resurrect documentation from the old symfony-cmf-docs repository

This commit is contained in:
David Buchmann
2024-04-03 10:58:30 +02:00
parent e06016ad6c
commit d3d19b641b
11 changed files with 2796 additions and 4 deletions

14
.doctrine-project.json Normal file
View File

@@ -0,0 +1,14 @@
{
"active": true,
"name": "PHPCR Bundle",
"slug": "phpcr-bundle",
"docsSlug": "doctrine-phpcr-bundle",
"versions": [
{
"name": "3.x",
"branchName": "3.x",
"slug": "latest",
"current": true
}
]
}

View File

@@ -19,8 +19,7 @@ adds features of its own like multilanguage.
## Documentation
For information, see [Symfony CMF Documentation](http://symfony.com/doc/master/cmf/index.html),
specifically [The Database Layer: PHPCR-ODM](http://symfony.com/doc/master/cmf/book/database_layer.html)
and [DoctrinePHPCRBundle](http://symfony.com/doc/master/cmf/bundles/phpcr_odm/introduction.html).
For information on PHPCR-ODM, see [Doctrine Documentation](https://www.doctrine-project.org/projects/phpcr-odm.html),
and [DoctrinePHPCRBundle](https://www.doctrine-project.org/projects/doctrine-phpcr-bundle.html).
PHPCR-ODM in general is documented in the [Doctrine PHPCR-ODM documentation](http://docs.doctrine-project.org/projects/doctrine-phpcr-odm/en/latest/).
Read more about PHPCR, the storage layer behind PHPCR-ODM: [PHPCR documentation](https://phpcr.readthedocs.io/en/latest/).

720
doc/configuration.rst Normal file
View File

@@ -0,0 +1,720 @@
Configuration Reference
=======================
The DoctrinePHPCRBundle can be configured under the ``doctrine_phpcr`` key in
your application configuration. When using XML, you can use the
``http://doctrine-project.org/schema/symfony-dic/odm/phpcr`` namespace.
Configuration
-------------
``session``
~~~~~~~~~~~
.. tip::
You can also configure multiple session. See
:doc:`multiple_sessions` for details.
.. configuration-block::
.. code-block:: yaml
# app/config/config.yml
doctrine_phpcr:
session:
backend:
type: X
# optional parameters for Jackalope
parameters:
jackalope.factory: Jackalope\Factory
jackalope.check_login_on_server: false
jackalope.disable_stream_wrapper: false
jackalope.auto_lastmodified: true
# see below for how to configure the backend of your choice
workspace: default
username: admin
password: admin
# tweak options for Jackalope (all versions)
options:
jackalope.fetch_depth: 1
.. code-block:: xml
<!-- app/config/config.xml -->
<?xml version="1.0" charset="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services">
<config xmlns="http://doctrine-project.org/schema/symfony-dic/odm/phpcr">
<session workspace="default" username="admin" password="admin">
<backend type="X">
<parameter key="jackalope.factory">Jackalope\Factory</parameter>
<parameter key="jackalope.check_login_on_server">false</parameter>
<parameter key="jackalope.disable_stream_wrapper">false</parameter>
<parameter key="jackalope.auto_lastmodified">true</parameter>
</backend>
<options jackalope.fetch_depth="1" />
</session>
</config>
</container>
.. code-block:: php
// app/config/config.php
$container->loadFromExtension('doctrine_phpcr', [
'session' => [
'backend' => [
'type' => 'X',
'parameters' => [
'jackalope.factory' => 'Jackalope\Factory',
'jackalope.check_login_on_server' => false,
'jackalope.disable_stream_wrapper' => false,
'jackalope.auto_lastmodified' => true,
],
],
'workspace' => 'default',
'username' => 'admin',
'password' => 'admin',
'options' => [
'jackalope.fetch_depth' => 1,
],
],
]);
``workspace``
"""""""""""""
**type**: ``string`` **required**
Defines the PHPCR workspace to use for this PHPCR session.
.. tip::
Every PHPCR implementation should provide the workspace called *default*,
but you can choose a different one. There is the
``doctrine:phpcr:workspace:create`` command to initialize a new workspace.
See also :ref:`bundles-phpcr-odm-commands`.
``username and password``
"""""""""""""""""""""""""
**type**: ``string`` **default**: ``null``
These credentials are used on the PHPCR layer for the
``PHPCR\SimpleCredentials``. They are optional for jackalope doctrine-dbal.
Do not confuse these credentials with the username and password used by
Doctrine DBAL to connect to the underlying RDBMS where the data
is actually stored.
``backend type``
""""""""""""""""
**type**: ``string`` **default**: ``jackrabbit``
This designates the PHPCR implementation. Valid options are
* ``jackrabbit``;
* ``doctrinedbal``;
* ``prismic``.
``backend parameters``
""""""""""""""""""""""
If you are using one of the Jackalope backends, you can set a couple of
parameters. This section explains the general parameters that are
available with all Jackalope backends. You can also
:ref:`activate logging and profiling <reference-configuration-phpcr-odm-logging>`.
``jackalope.factory``
.....................
**type**: ``string or object`` **default**: ``Jackalope\Factory``
Use a custom factory class for Jackalope objects.
``jackalope.check_login_on_server``
...................................
**type**: ``boolean`` **default**: ``false``
If set to ``false``, skip initial check whether repository exists. You will
only notice connectivity problems on the first attempt to use the repository.
``jackalope.disable_stream_wrapper``
....................................
**type**: ``boolean`` **default**: ``false``
If set to ``true``, streams are read immediately instead of on first access.
If you run into problems with streams this might be useful for debugging.
Otherwise you probably don't want to disable the wrappers, or all binaries
will be loaded each time their containing document is loaded, resulting in a
severe performance penalty.
``jackalope.auto_lastmodified``
...............................
**type**: ``boolean`` **default**: ``true``
Whether to automatically update nodes having ``mix:lastModified``.
See `last modified listener cookbook entry`_.
``backend curl_options``
""""""""""""""""""""""""
If you are using one of the Jackalope Jackrabbit backend, you can set
the curl options which are described in the php-documentation
`curl-setopt`_.
PHPCR Session with Jackalope Jackrabbit
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. configuration-block::
.. code-block:: yaml
# app/config/config.yml
doctrine_phpcr:
session:
backend:
type: jackrabbit
url: http://localhost:8080/server/
parameters:
# general parameters and options
# ...
# optional parameters specific to Jackalope Jackrabbit
jackalope.default_header: "X-ID: %serverid%"
jackalope.jackrabbit_expect: true
jackalope.jackrabbit_version: "2.18.3"
.. code-block:: xml
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services">
<config xmlns="http://doctrine-project.org/schema/symfony-dic/odm/phpcr">
<session>
<backend
type="jackrabbit"
url="http://localhost:8080/server/"
>
<parameter key="jackalope.default_header">X-ID: %serverid%</parameter>
<parameter key="jackalope.jackrabbit_expect">true</parameter>
<parameter key="jackalope.jackrabbit_version">2.18.3</parameter>
</backend>
</session>
</config>
</container>
.. code-block:: php
// app/config/config.php
$container->loadFromExtension('doctrine_phpcr', [
'session' => [
'backend' => [
'type' => 'jackrabbit',
'url' => 'http://localhost:8080/server/',
'parameters' => [
'jackalope.default_header' => 'X-ID: %serverid%',
'jackalope.jackrabbit_expect' => true,
'jackalope.jackrabbit_version' => '2.18.3',
],
],
],
]);
``url``
"""""""
**type**: ``string``, **required**
The configuration needs the ``url`` parameter to point to your Jackrabbit.
This looks like http://localhost:8080/server/
``jackalope.default_header``
""""""""""""""""""""""""""""
**type**: ``string``, **default**: ``null``
Set a default header to send on each request to the backend.
This is useful when using a load balancer between the webserver and jackrabbit,
to identify sessions.
``jackalope.jackrabbit_expect``
"""""""""""""""""""""""""""""""
**type**: ``boolean``, **default**: ``false``
Send the ``Expect: 100-continue`` header on larger PUT and POST requests.
Disabled by default to avoid issues with proxies and load balancers.
``jackalope.jackrabbit_version``
""""""""""""""""""""""""""""
**type**: ``string``, **default**: ``null``
.. versionadded:: 1.4.2
This configuration has been added in jackalope-jackrabbit version 1.4.2.
Set the version of the Jackrabbit server to allow the client to offer better functionality if possible.
For example, full UTF8 support including emojis in node and property names is possible when the Jackrabbit version is 2.18.0 or better.
PHPCR Session with Jackalope Doctrine DBAL
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This type uses Jackalope with a Doctrine database abstraction layer transport
to provide PHPCR without any installation requirements beyond any of the RDBMS
supported by Doctrine.
.. configuration-block::
.. code-block:: yaml
# app/config/config.yml
doctrine_phpcr:
session:
backend:
type: doctrinedbal
# if no explicit connection is specified, the default connection is used.
connection: default
# to configure caching
caches:
meta: doctrine_cache.providers.phpcr_meta
nodes: doctrine_cache.providers.phpcr_nodes
query: doctrine_cache.providers.phpcr_query
parameters:
# ... general parameters and options
# optional parameters specific to Jackalope Doctrine Dbal
jackalope.disable_transactions: false
.. code-block:: xml
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services">
<config xmlns="http://doctrine-project.org/schema/symfony-dic/odm/phpcr">
<session>
<backend type="doctrinedbal" connection="default">
<caches
meta="doctrine_cache.providers.phpcr_meta"
nodes="doctrine_cache.providers.phpcr_nodes"
query="doctrine_cache.providers.phpcr_query"
/>
<!-- ... general parameters and options -->
<!-- optional parameters specific to Jackalope Doctrine Dbal -->
<parameter key="jackalope.disable_transactions">false</parameter>
</backend>
</session>
</config>
</container>
.. code-block:: php
// app/config/config.php
$container->loadFromExtension('doctrine_phpcr', [
'session' => [
'backend' => [
'type' => 'doctrinedbal',
'connection' => 'default',
'caches' => [
'meta' => 'doctrine_cache.providers.phpcr_meta',
'nodes' => 'doctrine_cache.providers.phpcr_nodes',
'query' => 'doctrine_cache.providers.phpcr_query',
],
'parameters' => [
// ... general parameters and options
// optional parameters specific to Jackalope Doctrine Dbal
'jackalope.disable_transactions' => false,
],
],
],
]);
``connection``
""""""""""""""
**type**: ``string``, **default**: ``default``
Specify the Doctrine DBAL connection name to use if you don't want to use the
default connection. The name must be one of the names of the ``doctrine.dbal``
section of your Doctrine configuration, see the `Symfony Doctrine documentation`_.
``jackalope.disable_transactions``
""""""""""""""""""""""""""""""""""
**type**: ``boolean``, **default**: ``false``
Set to ``true`` to disable transactions. If transactions are enabled but not
actively used, every save operation is wrapped into a transaction.
Only allowed for doctrine-dbal because jackrabbit does not support
transactions.
.. _reference-configuration-phpcr-odm-logging:
Logging and Profiling
~~~~~~~~~~~~~~~~~~~~~
When using any of the Jackalope PHPCR implementations, you can activate logging
to log to the symfony log, or profiling to show information in the Symfony
debug toolbar:
.. configuration-block::
.. code-block:: yaml
# app/config/config.yml
doctrine_phpcr:
session:
backend:
# ...
logging: true
profiling: true
.. code-block:: xml
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services">
<config xmlns="http://doctrine-project.org/schema/symfony-dic/odm/phpcr">
<session>
<backend
logging="true"
profiling="true"
/>
</session>
</config>
</container>
.. code-block:: php
// app/config/config.yml
$container->loadFromExtension('doctrine_phpcr', [
'session' => [
'backend' => [
// ...
'logging' => true,
'profiling' => true,
],
],
]);
Doctrine PHPCR-ODM Configuration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This configuration section manages the Doctrine PHPCR-ODM system. If you do
not configure anything here, the ODM services will not be loaded.
.. tip::
If you want to only use plain PHPCR without the PHPCR-ODM, you can simply
not configure the ``odm`` section to avoid loading the services at all.
Note that most CMF bundles by default use PHPCR-ODM documents and thus
need ODM enabled.
.. tip::
You can also configure multiple document managers. See
:doc:`multiple_sessions` for details.
.. configuration-block::
.. code-block:: yaml
# app/config/config.yml
doctrine_phpcr:
odm:
configuration_id: ~
auto_mapping: true
mappings:
# An array of mapping, which may be a bundle name or an unique name
<name>:
mapping: true
type: ~
dir: ~
alias: ~
prefix: ~
is_bundle: ~
auto_generate_proxy_classes: "%kernel.debug%"
proxy_dir: "%kernel.cache_dir%/doctrine/PHPCRProxies"
proxy_namespace: PHPCRProxies
namespaces:
translation:
alias: phpcr_locale
metadata_cache_driver:
type: array
host: ~
port: ~
instance_class: ~
class: ~
id: ~
namespace: ~
.. code-block:: xml
<!-- app/config/config.xml -->
<?xml version="1.0" charset="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services">
<config xmlns="http://doctrine-project.org/schema/symfony-dic/odm/phpcr">
<odm configuration-id="null"
auto-mapping="true"
auto-generate-proxy-classes="%kernel.debug%"
proxy-dir="%kernel.cache_dir%/doctrine/PHPCRProxies"
proxy-namespace="PHPCRProxies"
>
<namespaces>
<translation alias="phpcr_locale" />
</namespaces>
<!-- An array of mapping, which may be a bundle name or an unique name -->
<mapping name="<name>">
mapping="true"
type="null"
dir="null"
alias="null"
prefix="null"
is-bundle="null"
/>
<metadata-cache-driver
type="array"
host="null"
port="null"
instance-class="null"
class="null"
id="null"
namespace="null"
/>
</odm>
</config>
</container>
.. code-block:: php
// app/config/config.php
$container->loadFromExtension('doctrine_phpcr', [
'odm' => [
'configuration_id' => null,
'auto_mapping' => true,
'auto_generate_proxy_classes' => '%kernel.debug%',
'proxy-dir' => '%kernel.cache_dir%/doctrine/PHPCRProxies',
'proxy_namespace' => 'PHPCRProxies',
'namespaces' => [
'translation' => [
'alias' => 'phpcr_locale',
],
],
'mappings' => [
// An array of mapping, which may be a bundle name or an unique name
'<name>' => [
'mapping' => true,
'type' => null,
'dir' => null,
'alias' => null,
'prefix' => null,
'is-bundle' => null,
],
],
'metadata_cache_driver' => [
'type' => 'array',
'host' => null,
'port' => null,
'instance_class' => null,
'class' => null,
'id' => null,
'namespace' => null,
],
],
]);
``configuration_id``
""""""""""""""""""""
**type**: ``string``, **default**: ``doctrine_phpcr.odm.configuration``
The service to use as base for building the PHPCR-ODM configuration.
``auto_mapping``
""""""""""""""""
**type**: ``boolean``, **default**: ``true``
When enabled, bundles will be automatically loaded and attempted to resolve
mappings by convention in
``<Bundle>/Resources/config/doctrine/<Document>.phpcr.xml`` resp. ``*.phpcr.yml``
to configure mappings for documents you provide in the ``<Bundle>/Document``
folder. Otherwise you need to manually configure the mappings section.
``auto_generate_proxy_classes``
"""""""""""""""""""""""""""""""
**type**: ``boolean``, **default**: ``%kernel.debug%``
When disabled, you need to run the ``cache:warmup`` command in order to have
the proxy classes generated after you modified a document.
``proxy_dir``
"""""""""""""
**type**: ``string``, **default**: ``%kernel.cache_dir%/doctrine/PHPCRProxies``
Change folder where proxy classes are generated.
``proxy_namespace``
"""""""""""""""""""
**type**: ``string``, **default**: ``PHPCRProxies``
Change namespace for generated proxy classes.
``namespaces``
""""""""""""""
This configuration section is intended to allow you to customize the
PHPCR namespaces used by PHPCR-ODM. Currently it is only possible to
set the alias used by the translation strategy.
``mappings``
""""""""""""
Explicitly define document mappings by configuration. For modern Symfony
applications that do not use a bundle, it is necessary to configure mappings.
For bundles, if ``auto_mapping`` is enabled, you don't usually need to.
.. tip::
When ``auto_mapping`` is disabled, you need to explicitly list the
bundles handled by this document manager. Usually its fine to just list
the bundle names without any actual configuration.
.. tip::
DoctrinePhpcrBundle is integrated with symfony/doctrine-bridge (in the same
way that `Doctrine ORM`_ does), relying on the bridge to process mapping
configuration options. Therefore, the mapping options work nearly the same
across two bundles.
There are several configuration options that you can control as part of
a mapping definition:
``mapping``
A boolean value and it is usually ``true``. Set it to ``true`` to
declare it as a mapping and allow the document manager to pick it
up.
``type``
One of ``attribute``, ``xml``, ``yml``, ``php`` or ``staticphp``.
This specifies which type of metadata type your mapping uses.
``dir``
Path to the mapping or document files (depending on the driver). If this path
is relative, it is assumed to be relative to the bundle root. This only works
if the name of your mapping is a bundle name. If you want to use this option
to specify absolute paths, you should prefix the path with the kernel
parameters that exist in the DIC (for example ``%kernel.root_dir%``).
``prefix``
A common namespace prefix that all documents of this mapping share. This
prefix should never conflict with prefixes of other defined mappings
otherwise some of your documents cannot be found by Doctrine. This option
defaults to the bundle namespace + ``Document``, for example for an
application bundle called ``AcmeHelloBundle`` prefix would be
``Acme\HelloBundle\Document``.
``alias``
Doctrine offers a way to alias document namespaces to simpler, shorter names
to be used in DQL queries or for Repository access. When using a bundle, the
alias defaults to the bundle name.
``is_bundle``
This option is a derived value from ``dir`` and by default is set to true if
dir is relative proved by a ``file_exists()`` check that returns false. It
is false if the existence check returns true. In this case, an absolute path
was specified and the metadata files are most likely in a directory outside
of a bundle.
``metadata_cache_driver``
"""""""""""""""""""""""""
Configure a cache driver for the Doctrine metadata. This is the same as for
`Doctrine ORM`_.
The ``namespace`` value is useful if you are using one primary caching server
for multiple sites that have similar code in their respective ``vendor/``
directories. By default, Symfony will try to generate a unique namespace
value for each application but if code is very similar between two
applications, it is very easy to have two applications share the same
namespace. This option also prevents Symfony from needing to re-build
application cache on each Composer update on a newly generated namespace.
General Settings
~~~~~~~~~~~~~~~~
.. configuration-block::
.. code-block:: yaml
# app/config/config.yml
doctrine_phpcr:
jackrabbit_jar: /path/to/jackrabbit.jar
dump_max_line_length: 120
.. code-block:: xml
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services">
<config xmlns="http://doctrine-project.org/schema/symfony-dic/odm/phpcr"
jackrabbit-jar="/path/to/jackrabbit.jar"
dump-max-line-length="120"
/>
</container>
.. code-block:: php
// app/config/config.php
$container->loadFromExtension('doctrine_phpcr', [
'jackrabbit_jar' => '/path/to/jackrabbit.jar',
'dump_max_line_length' => 120,
]);
``jackrabbit_jar``
""""""""""""""""""
**type**: ``string`` **default**: ``null``
Absolute path to the jackrabbit jar file. If this is set, you can use the
``doctrine:phpcr:jackrabbit`` console command to start and stop Jackrabbit.
``dump_max_line_length``
""""""""""""""""""""""""
**type**: ``integer`` **default**: ``120``
For tuning the output of the ``doctrine:phpcr:dump`` command.
.. _`Symfony Doctrine documentation`: https://symfony.com/doc/current/doctrine.html
.. _`last modified listener cookbook entry`: http://docs.doctrine-project.org/projects/doctrine-phpcr-odm/en/latest/cookbook/last-modified.html
.. _`Doctrine ORM`: https://symfony.com/doc/current/reference/configuration/doctrine.html#caching-drivers
.. _`curl-setopt`: http://php.net/manual/de/function.curl-setopt.php

101
doc/events.rst Normal file
View File

@@ -0,0 +1,101 @@
.. index::
single: Events; DoctrinePHPCRBundle
Doctrine PHPCR-ODM Events
=========================
Doctrine PHPCR-ODM provides an event system allowing to react to all
important operations that documents have during their lifecycle. Please
see the `Doctrine PHPCR-ODM event system documentation`_ for a full
list of supported events.
The DoctrinePHPCRBundle provides dependency injection support for the
event listeners and event subscribers.
Dependency Injection Tags
-------------------------
You can tag services to listen to Doctrine PHPCR-ODM events. It works the same
way as for `Doctrine ORM events`_. The only differences are:
* use the tag name ``doctrine_phpcr.event_listener`` resp.
``doctrine_phpcr.event_subscriber`` instead of ``doctrine.event_listener``;
* expect the argument to be of class
``Doctrine\Common\Persistence\Event\LifecycleEventArgs``.
To tag a service as event listener and another service as event subscriber,
use this configuration:
.. configuration-block::
.. code-block:: yaml
# app/config/services.yml
services:
app.phpcr_search_indexer:
class: App\EventListener\SearchIndexer
tags:
- { name: doctrine_phpcr.event_listener, event: postPersist }
app.phpcr_listener:
class: App\EventListener\MyListener
tags:
- { name: doctrine_phpcr.event_subscriber }
.. code-block:: xml
<?xml version="1.0" ?>
<!-- app/config/config.xml -->
<container xmlns="http://symfony.com/schema/dic/services">
<services>
<service id="app.phpcr_search_indexer"
class="App\EventListener\SearchIndexer">
<tag name="doctrine_phpcr.event_listener" event="postPersist" />
</service>
<service id="app.phpcr_listener"
class="App\EventListener\MyListener">
<tag name="doctrine_phpcr.event_subscriber" />
</service>
</services>
</container>
.. code-block:: php
// app/config/config.php
use App\EventListener\SearchIndexer;
use App\EventListener\MyListener;
$container
->register(
'app.phpcr_search_indexer',
SearchIndexer::class
)
->addTag('doctrine_phpcr.event_listener', [
'event' => 'postPersist',
])
;
$container
->register(
'app.phpcr_listener',
MySubscriber::class
)
->addTag('doctrine_phpcr.event_subscriber')
;
.. tip::
Doctrine event subscribers (both ORM and PHPCR-ODM) can **not** return a
flexible array of methods to call like the `Symfony event subscriber`_.
Doctrine event subscribers must return a simple array of the event
names they subscribe to. Doctrine will then expect methods on the
subscriber with the names of the subscribed events, just as when using an
event listener.
You can find more information and examples of the doctrine event system
in "`How to Register Event Listeners and Subscribers`_" of the core documentation.
.. _`Doctrine PHPCR-ODM event system documentation`: http://docs.doctrine-project.org/projects/doctrine-phpcr-odm/en/latest/reference/events.html
.. _`Symfony event subscriber`: https://symfony.com/doc/current/components/event_dispatcher/introduction.html#using-event-subscribers
.. _`Doctrine ORM events`: https://symfony.com/doc/current/doctrine/event_listeners_subscribers.html
.. _`How to Register Event Listeners and Subscribers`: https://symfony.com/doc/current/doctrine/event_listeners_subscribers.html

View File

@@ -0,0 +1,306 @@
.. index::
single: Initializers; DoctrinePHPCRBundle
single: Fixtures; DoctrinePHPCRBundle
single: Migrators; DoctrinePHPCRBundle
Maintaining Data in the Repository
==================================
PHPCR-ODM provides *initializers* that ensure a repository is ready for
production use, *migrators* to programmatically load data and
*fixture loading* for handling testing and demo fixtures.
.. _phpcr-odm-repository-initializers:
Repository Initializers
-----------------------
The Initializer is the PHPCR equivalent of the ORM schema tools. It is used to
let your application PHPCR node types and to create required base paths in the
repository.
.. note::
The concept of base paths is needed because there are no separate "tables"
as in a relational database, but one tree containing all data. To be able
to add a document, you need to ensure the parent path is already present
in the repository.
Initializers have to implement the
``Doctrine\Bundle\PHPCRBundle\Initializer\InitializerInterface``. If you don't
need any special logic and want to create plain PHPCR nodes and not documents,
you can simply define services with ``GenericInitializer``. The generic
Initializer expects a name to identify the Initializer, an array of repository
paths it will create if they do not exist and an optional string defining
namespaces and primary / mixin node types in the CND language that should be
registered with the repository.
A service to use the generic Initializer looks like this:
.. configuration-block::
.. code-block:: yaml
# app/config/services.yml
app.phpcr_initializer:
class: Doctrine\Bundle\PHPCRBundle\Initializer\GenericInitializer
arguments:
- App Basepaths
- ["/my/content", "/my/menu"]
- "%app.cnd%"
tags:
- { name: "doctrine_phpcr.initializer" }
.. code-block:: xml
<!-- app/config/services.xml -->
<service id="app.phpcr_initializer"
class="Doctrine\Bundle\PHPCRBundle\Initializer\GenericInitializer">
<argument>App Basepaths</argument>
<argument type="collection">
<argument>/my/content</argument>
<argument>/my/menu</argument>
</argument>
<argument>%app.cnd%</argument>
<tag name="doctrine_phpcr.initializer"/>
</service>
.. code-block:: php
// app/config/services.php
use Doctrine\Bundle\PHPCRBundle\Initializer\GenericInitializer;
use Symfony\Component\DependencyInjection\Definition
// ...
$definition = new Definition(
GenericInitializer::class, [
'App Basepaths',
['/my/content', '/my/menu'],
'%app.cnd%',
]
);
$definition->addTag('doctrine_phpcr.initializer');
$container->setDefinition('app.phpcr_initializer', $definition);
You can execute your Initializers using the following command:
.. code-block:: bash
$ php bin/console doctrine:phpcr:repository:init
.. note::
The load data fixtures command automatically executes the Initializers
after purging the database, before executing the fixtures.
The generic Initializer only creates PHPCR nodes. If you want to create
specific documents, you need your own Initializer. The interesting method
to overwrite is the ``init`` method. It is passed the ``ManagerRegistry``,
from which you can retrieve the PHPCR session but also the document manager::
// src/App/Initializer/SiteInitializer.php
namespace App\Initializer;
use App\Documents\Site;
use Doctrine\Bundle\PHPCRBundle\Initializer\InitializerInterface;
use Doctrine\Bundle\PHPCRBundle\ManagerRegistry;
use PHPCR\SessionInterface;
use PHPCR\Util\NodeHelper;
class SiteInitializer implements InitializerInterface
{
private $basePath;
public function __construct($basePath = '/cms')
{
$this->basePath = $basePath;
}
public function init(ManagerRegistry $registry)
{
$dm = $registry->getManagerForClass(Site::class);
if ($dm->find(null, $this->basePath)) {
return;
}
$site = new Site();
$site->setId($this->basePath);
$dm->persist($site);
$dm->flush();
$session = $registry->getConnection();
// create the 'cms', 'pages', and 'posts' nodes
NodeHelper::createPath($session, '/cms/pages');
NodeHelper::createPath($session, '/cms/posts');
NodeHelper::createPath($session, '/cms/routes');
$session->save();
}
public function getName()
{
return 'Site Initializer';
}
}
Define a service for your Initializer as follows:
.. configuration-block::
.. code-block:: yaml
# app/config/config.yml
services:
# ...
app.phpcr_initializer_site:
class: App\Initializer\SiteInitializer
tags:
- { name: doctrine_phpcr.initializer }
.. code-block:: xml
<!-- app/config/config.php
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:acme_demo="http://www.example.com/symfony/schema/"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">
<!-- ... -->
<services>
<!-- ... -->
<service id="app.phpcr_initializer_site"
class="App\Initializer\SiteInitializer">
<tag name="doctrine_phpcr.initializer"/>
</service>
</services>
</container>
.. code-block:: php
// app/config/config.php
// ...
$container
->register(
'app.phpcr_initializer_site',
'App\Initializer\SiteInitializer'
)
->addTag('doctrine_phpcr.initializer', ['name' => 'doctrine_phpcr.initializer']
;
Migration Loading
-----------------
The DoctrinePHPCRBundle also ships with a simple command to run migration
scripts. Migrations should implement the
``Doctrine\Bundle\PHPCRBundle\Migrator\MigratorInterface`` and registered as a
service with a ``doctrine_phpcr.migrator`` tag contains an ``alias`` attribute
uniquely identifying the migrator. There is an optional
``Doctrine\Bundle\PHPCRBundle\Migrator\AbstractMigrator`` class to use as a
basis.
.. configuration-block::
.. code-block:: yaml
# app/config/services.yml
app.migration:
class: App\Migration\Migration
arguments:
- { "%app.content_basepath%", "%app.menu_basepath%" }
tags:
- { name: "doctrine_phpcr.migrator", alias: "app.migration" }
.. code-block:: xml
<!-- app/config/services.xml -->
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services">
<service id="app.migration"
class="App\Migration\Migration">
<argument type="collection">
<argument>%app.content_basepath%</argument>
<argument>%app.menu_basepath%</argument>
</argument>
<tag name="doctrine_phpcr.migrator" alias="app.migration"/>
</service>
</container>
.. code-block:: php
use App\Migration\Migration;
use Symfony\Component\DependencyInjection\Definition;
// ...
$definition = new Definition(Migration::class, [
[
'%app.content_basepath%',
'%app.menu_basepath%',
],
]);
$definition->addTag('doctrine_phpcr.migrator', ['alias' => 'app.migration']);
$container->setDefinition('app.migration', $definition);
To find out available migrations run:
.. code-block:: bash
$ php bin/console doctrine:phpcr:migrator:migrate
Then pass in the name of the migrator to run it, optionally passing in an
``--identifier``, ``--depth`` or ``--session`` argument. The later argument
determines which session name to set on the migrator, while the first two
arguments will simply be passed to the ``migrate()`` method. You can find an
example migrator in the SimpleCmsBundle.
.. tip::
A simple alternative if you do not need to reproduce the result can be to
export part of your repository and re-import it on the target server. This
is described in :ref:`phpcr-odm-backup-restore`.
.. _phpcr-odm-repository-fixtures:
Fixture Loading
---------------
To use the ``doctrine:phpcr:fixtures:load`` command, you additionally need to
install the `DoctrineFixturesBundle`_ which brings the
`Doctrine data-fixtures`_ into Symfony.
Fixtures work the same way they work for Doctrine ORM. You write fixture
classes implementing ``Doctrine\Common\DataFixtures\FixtureInterface``. If you
place them in ``<App|Bundle>\DataFixtures\PHPCR``, they will be auto detected if you
don't specify a path in the command.
A simple example fixture class looks like this::
// src/App/DataFixtures/PHPCR/LoadPageData.php
namespace App\DataFixtures\PHPCR;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\ODM\PHPCR\DocumentManager;
class LoadPageData implements FixtureInterface
{
public function load(ObjectManager $manager)
{
if (!$manager instanceof DocumentManager) {
$class = get_class($manager);
throw new \RuntimeException("Fixture requires a PHPCR ODM DocumentManager instance, instance of '$class' given.");
}
// ... create and persist your data here
}
}
For more on fixtures, see the documentation of the `DoctrineFixturesBundle`_.
.. _`DoctrineFixturesBundle`: https://symfony.com/doc/current/bundles/DoctrineFixturesBundle/index.html
.. _`Doctrine data-fixtures`: https://github.com/doctrine/data-fixtures

183
doc/forms.rst Normal file
View File

@@ -0,0 +1,183 @@
.. index::
single: Form Types; DoctrinePHPCRBundle
Doctrine PHPCR-ODM Form Types
=============================
This bundle provides some handy form types for PHPCR and PHPCR-ODM specific
cases, along with a type guesser that uses these types.
There is also a validator constraint for PHPCR-ODM documents.
Form Types
----------
.. tip::
When editing associative multivalue fields, have a look at the
BurgovKeyValueFormBundle_.
phpcr_document
~~~~~~~~~~~~~~
This form type is suitable to edit associations of PHPCR-ODM documents. It
works for ReferenceOne, ReferenceMany and Referrers but also for
ParentDocument associations. Make sure to set the ``multiple`` option
for ReferenceMany and Referrers, and to not set it for the others.
.. note::
While ``Children`` is also an association, it makes no sense to edit it
with this form type. Children are automatically attached to their parent.
``MixedReferrers`` could be shown as a ``disabled`` field but never edited,
because this association is immutable.
This form type is equivalent to the ``entity`` form type provided by Symfony
for Doctrine ORM. It has the same options as the ``entity`` type, including
that the option for the document manager is called ``em``.
A simple example of using the ``phpcr_document`` form type looks as follows::
use App\Document\TargetClass;
$form
->add(
'speakers',
'phpcr_document',
[
'property' => 'title',
'class' => TargetClass::class,
'multiple' => true,
]
)
;
This will produce a multiple choice select field with the value of
``getTitle`` called on each instance of ``TargetClass`` found in the
content repository. Alternatively, you can set the ``choices`` option
to a list of allowed managed documents. Please refer to the
`Symfony documentation on the entity form type`_ for more details,
including how you can configure a query.
If you are using SonataDoctrinePHPCRAdminBundle_, you might want to look into
``sonata_type_collection``. That form type allows to edit related
documents (references as well as children) in-line and also to create
and remove them on the fly.
phpcr_odm_reference_collection
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. caution::
This form type was deprecated in DoctrinePHPCRBundle 1.1 and will be
removed in DoctrinePHPCRBundle 1.2. You should use the `phpcr_document`_
type instead, which can do the same but better.
This form type handles editing ``ReferenceMany`` collections on PHPCR-ODM
documents. It is a choice field with an added ``referenced_class`` required
option that specifies the class of the referenced target document.
To use this form type, you also need to specify the list of possible reference
targets as an array of PHPCR-ODM ids or PHPCR paths.
The minimal code required to use this type looks as follows::
use App\Document\Article;
$dataArr = [
'/some/phpcr/path/item_1' => 'first item',
'/some/phpcr/path/item_2' => 'second item',
];
$formMapper
->with('form.group_general')
->add('myCollection', 'phpcr_odm_reference_collection', [
'choices' => $dataArr,
'referenced_class' => Article::class,
])
->end();
.. tip::
When building an admin interface with the SonataDoctrinePHPCRAdminBundle_
there is also the ``sonata_type_model``, which is more powerful, allowing to
add to the referenced documents on the fly.
phpcr_reference
~~~~~~~~~~~~~~~
The ``phpcr_reference`` represents a PHPCR Property of type REFERENCE or
WEAKREFERENCE within a form. The input will be rendered as a text field
containing either the PATH or the UUID as per the configuration. The form will
resolve the path or id back to a PHPCR node to set the reference.
This type extends the ``text`` form type. It adds an option
``transformer_type`` that can be set to either ``path`` or ``uuid``.
Validator Constraint
--------------------
The bundle provides a ``ValidPhpcrOdm`` constraint validator you can use to
check if your document ``Id`` or ``Nodename`` and ``Parent`` fields are
correct.
.. configuration-block::
.. code-block:: yaml
# src/App/Resources/config/validation.yml
App\Document\Author:
constraints:
- Doctrine\Bundle\PHPCRBundle\Validator\Constraints\ValidPhpcrOdm
.. code-block:: php
// src/App/Document/Author.php
// ...
use Doctrine\Bundle\PHPCRBundle\Validator\Constraints as OdmAssert;
#[OdmAssert\ValidPhpcrOdm]
class Author
{
// ...
}
.. code-block:: xml
<!-- Resources/config/validation.xml -->
<?xml version="1.0" ?>
<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping
http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">
<class name="App\Document\Author">
<constraint name="Doctrine\Bundle\PHPCRBundle\Validator\Constraints\ValidPhpcrOdm" />
</class>
</constraint-mapping>
.. code-block:: php
// src/App/Document/Author.php
// ...
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Doctrine\Bundle\PHPCRBundle\Validator\Constraints as OdmAssert;
#[OdmAssert\ValidPhpcrOdm]
class Author
{
// ...
public static function loadValidatorMetadata(ClassMetadata $metadata)
{
$metadata->addConstraint(new OdmAssert\ValidPhpcrOdm());
}
}
.. _BurgovKeyValueFormBundle: https://github.com/Burgov/KeyValueFormBundle
.. _`Symfony documentation on the entity form type`: https://symfony.com/doc/current/reference/forms/types/entity.html
.. _SonataDoctrinePHPCRAdminBundle: https://sonata-project.org/bundles/doctrine-phpcr-admin/master/doc/index.html

14
doc/index.rst Normal file
View File

@@ -0,0 +1,14 @@
DoctrinePHPCRBundle
===================
.. toctree::
:maxdepth: 2
introduction
models
events
forms
fixtures_initializers
multilang
multiple_sessions
configuration

568
doc/introduction.rst Normal file
View File

@@ -0,0 +1,568 @@
.. index::
single: PHPCR; Bundles
single: DoctrinePHPCRBundle
DoctrinePHPCRBundle
===================
The `DoctrinePHPCRBundle`_ provides integration with the PHP content
repository and optionally with Doctrine PHPCR-ODM to provide the ODM document
manager in symfony.
Out of the box, this bundle supports the following PHPCR implementations:
* `Jackalope`_ (Jackrabbit, Doctrine DBAL and prismic transports)
.. tip::
This reference only explains the Symfony integration of PHPCR and
PHPCR-ODM. To learn how to use PHPCR, refer to `the PHPCR website`_ and
for Doctrine PHPCR-ODM to the `PHPCR-ODM documentation`_.
Setup
-----
Requirements
~~~~~~~~~~~~
* When using **jackalope-jackrabbit**: Java, Apache Jackalope and ``libxml``
version >= 2.7.0 (due to a `bug in libxml`_)
* When using **jackalope-doctrine-dbal with MySQL**: MySQL >= 5.1.5
(as you need the xml function ``ExtractValue``)
Installation
------------
You can install this bundle `with composer`_ using the
`doctrine/phpcr-bundle`_ package. You need a concrete implementation of
the PHPCR API. For this example, we assume that you require Jackalope Doctrine
DBAL. See the `PHPCR-ODM documentation` for alternatives.
If you want to use PHPCR-ODM, you additionally need to require
``doctrine/phpcr-odm``.
.. code-block:: javascript
require: {
...
"jackalope/jackalope-doctrine-dbal": "1.2.*",
"doctrine/phpcr-odm": "1.2.*",
"doctrine/phpcr-bundle": "1.2.*",
...
}
Besides the ``DoctrinePHPCRBundle`` you also need to instantiate the base
``DoctrineBundle`` in your kernel::
// app/AppKernel.php
// ...
class AppKernel extends Kernel
{
public function registerBundles()
{
$bundles = [
// ...
new Doctrine\Bundle\PHPCRBundle\DoctrinePHPCRBundle(),
new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
];
// ...
}
// ...
}
Configuration
-------------
PHPCR Session Configuration
~~~~~~~~~~~~~~~~~~~~~~~~~~~
The session needs a PHPCR implementation specified in the ``backend`` section
by the ``type`` field, along with configuration options to bootstrap the
implementation. The examples here assume that you are using Jackalope Doctrine
DBAL. The full documentation is in the :doc:`configuration reference <configuration>`.
To use Jackalope Doctrine DBAL, you need to configure a database connection
with the DoctrineBundle. For detailed information, see the
`Symfony Doctrine documentation`_. A simple example is:
.. code-block:: yaml
# app/config/parameters.yml
parameters:
database_driver: pdo_mysql
database_host: localhost
database_name: test_project
database_user: root
database_password: password
# ...
.. configuration-block::
.. code-block:: yaml
# app/config/config.yml
doctrine:
dbal:
driver: "%database_driver%"
host: "%database_host%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
.. code-block:: xml
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:doctrine="http://symfony.com/schema/dic/doctrine"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/doctrine http://symfony.com/schema/dic/doctrine/doctrine-1.0.xsd">
<doctrine:config>
<doctrine:dbal
driver="%database_driver%"
host="%database_host%"
dbname="%database_name%"
user="%database_user%"
password="%database_password%"
/>
</doctrine:config>
</container>
.. code-block:: php
// app/config/config.php
$configuration->loadFromExtension('doctrine', [
'dbal' => [
'driver' => '%database_driver%',
'host' => '%database_host%',
'dbname' => '%database_name%',
'user' => '%database_user%',
'password' => '%database_password%',
],
]);
Jackalope Doctrine DBAL provides a PHPCR implementation without any
installation requirements beyond any of the RDBMS supported by Doctrine.
Once you set up Doctrine DBAL, you can configure Jackalope:
.. configuration-block::
.. code-block:: yaml
# app/config/config.yml
doctrine_phpcr:
session:
backend:
type: doctrinedbal
# connection: default
# requires DoctrineCacheBundle
# caches:
# meta: doctrine_cache.providers.phpcr_meta
# nodes: doctrine_cache.providers.phpcr_nodes
# enable logging
logging: true
# enable profiling in the debug toolbar.
profiling: true
workspace: default
username: admin
password: admin
.. code-block:: xml
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services">
<config xmlns="http://doctrine-project.org/schema/symfony-dic/odm/phpcr">
<session
workspace="default"
username="admin"
password="admin"
>
<backend
type="doctrinedbal"
logging="true"
profiling="true"
>
<!-- connection="default" - option on <backend> to change dbal connection -->
<!--
<caches
meta="doctrine_cache.providers.phpcr_meta"
nodes="doctrine_cache.providers.phpcr_nodes"
/>
-->
</backend>
</session>
</config>
</container>
.. code-block:: php
// app/config/config.php
$container->loadFromExtension('doctrine_phpcr', [
'session' => [
'backend' => [
'type' => 'doctrinedbal',
//'connection': 'default',
'logging' => true,
'profiling' => true,
//'caches' => [
// 'meta' => 'doctrine_cache.providers.phpcr_meta'
// 'nodes' => 'doctrine_cache.providers.phpcr_nodes'
//],
],
'workspace' => 'default',
'username' => 'admin',
'password' => 'admin',
],
]);
Now make sure the database exists and initialize it:
.. code-block:: bash
# without Doctrine ORM
php bin/console doctrine:database:create
php bin/console doctrine:phpcr:init:dbal
.. tip::
You can also use a different doctrine dbal connection instead of the
default. Specify the dbal connection name in the ``connection`` option of
the ``backend`` configuration.
It is recommended to use a separate connection to a separate database if
you also use Doctrine ORM or direct DBAL access to data, rather than
mixing this data with the tables generated by Jackalope Doctrine Dbal. If
you have a separate connection, you need to pass the alternate connection
name to the ``doctrine:database:create`` command with the ``--connection``
option. For Doctrine PHPCR commands, this parameter is not needed as you
configured the connection to use.
If you are using Doctrine ORM on the same connection, the schema is integrated
into ``doctrine:schema:create|update|drop`` and also `DoctrineMigrationsBundle`_
so that you can create migrations.
.. code-block:: bash
# Using Doctrine ORM
php bin/console doctrine:database:create
php bin/console doctrine:schema:create
.. note::
To use the cache, install and configure the DoctrineCacheBundle and uncomment
the cache meta and nodes settings.
Doctrine PHPCR-ODM Configuration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This configuration section manages the document mapper system that converts
your PHPCR nodes to domain model objects. If you do not configure anything
here, the ODM services will not be loaded.
.. configuration-block::
.. code-block:: yaml
# app/config/config.yml
doctrine_phpcr:
odm:
auto_mapping: true
auto_generate_proxy_classes: "%kernel.debug%"
mappings:
App:
mapping: true
type: attribute
dir: '%kernel.root_dir%/Document'
alias: App
prefix: App\Document\
is_bundle: false
.. code-block:: xml
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services">
<config xmlns="http://doctrine-project.org/schema/symfony-dic/odm/phpcr">
<odm
auto-mapping="true"
auto-generate-proxy-classes="%kernel.debug%"
>
<mapping name="App"
mapping="true"
type="attribute"
dir="%kernel.root_dir%/Document"
alias="App"
prefix="App\Document\"
is_bundle="false"
/>
</odm>
</config>
</container>
.. code-block:: php
// app/config/config.php
$container->loadFromExtension('doctrine_phpcr', [
'odm' => [
'auto_mapping' => true,
'auto_generate_proxy_classes' => '%kernel.debug%',
'mappings' => [
# Configure document mappings
'App' => [
'mapping' => true,
'type' => 'attribute',
'dir' => '%kernel.root_dir%/Document',
'alias' => 'App',
'prefix' => 'App\Document\',
'is-bundle' => false,
],
],
],
]);
When ``auto_mapping`` is enabled, bundles will be automatically loaded and
attempted to resolve mappings
.. tip::
For bundles, unless you disable ``auto_mapping``, you can place your
documents in the ``Document`` folder inside your bundles and use
attribute or name the mapping files following this convention:
``<Bundle>/Resources/config/doctrine/<DocumentClass>.phpcr.xml`` or
``*.phpcr.yml``.
If ``auto_generate_proxy_classes`` is false, you need to run the
``cache:warmup`` command in order to have the proxy classes generated after
you modified a document. This is usually done in production to gain some performance.
For applications, it is usually required to define ``mappings``. In a standard
minimal setup, an ``App`` definition as shown in above example is required,
which maps ``App\Document\`` documents in the ``src/Document`` directory.
See :doc:`configuration`, for complete details.
Registering System Node Types
"""""""""""""""""""""""""""""
PHPCR-ODM uses a `custom node type`_ to track meta information without
interfering with your content. There is a command that makes it trivial to
register this type and the PHPCR namespace, as well as all base paths of
bundles:
.. code-block:: bash
$ php bin/console doctrine:phpcr:repository:init
You only need to run this command once when you created a new repository. (But
nothing goes wrong if you run it on each deployment for example.)
Profiling and Performance of Jackalope
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When using any of the Jackalope PHPCR implementations, you can activate logging
to log to the symfony log, or profiling to show information in the Symfony
debug toolbar:
.. configuration-block::
.. code-block:: yaml
# app/config/config.yml
doctrine_phpcr:
session:
backend:
# ...
logging: true
profiling: true
.. code-block:: xml
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services">
<config xmlns="http://doctrine-project.org/schema/symfony-dic/odm/phpcr">
<session>
<backend
logging="true"
profiling="true"
/>
</session>
</config>
</container>
.. code-block:: php
// app/config/config.yml
$container->loadFromExtension('doctrine_phpcr', [
'session' => [
'backend' => [
// ...
'logging' => true,
'profiling' => true,
],
],
]);
Now that you can see the effects of changes, you can try if adjusting the global
fetch depth reduces the number and duration for queries. Set the option
``jackalope.fetch_depth`` to something bigger than 0 to have Jackalope pre-fetch
children or whole subtrees. This can reduce the number of queries needed, but
watch out for longer queries because more data is fetched.
When using Jackalope Doctrine DBAL, it is highly recommended to activate the
caching options.
Note that you can also set the fetch-depth on the session on the fly for
specific calls, or use the fetch-depth option on children mappings of your
documents.
The parameter ``jackalope.check_login_on_server`` can be set to false to save
an initial call to the database to check if the connection works.
Services
--------
There are 3 main services provided by this bundle:
* ``Doctrine\Bundle\PHPCRBundle\ManagerRegistry``- The ``ManagerRegistry``
instance with references to all sessions and document manager instances;
* ``PHPCR\SessionInterface`` - the PHPCR session. If you configured
multiple sessions, this will be the default session;
* ``Doctrine\ODM\PHPCR\DocumentManagerInterface`` - the PHPCR-ODM document
manager. If you configured multiple managers, this will be the default
manager.
.. _bundles-phpcr-odm-commands:
Doctrine PHPCR Commands
-----------------------
All commands about PHPCR are prefixed with ``doctrine:phpcr`` and you can use
the --session argument to use a non-default session if you configured several
PHPCR sessions.
Some of these commands are specific to a backend or to the ODM. Those commands
will only be available if such a backend is configured.
Use ``php bin/console help <command>`` to see all options each of the commands
has.
* **doctrine:phpcr:document:migrate-class**: Command to migrate document classes;
* **doctrine:phpcr:fixtures:load**: Load data fixtures to your PHPCR database;
* **doctrine:phpcr:init:dbal**: Prepare the database for Jackalope Doctrine-Dbal;
* **doctrine:phpcr:jackrabbit**: Start and stop the Jackrabbit server;
* **doctrine:phpcr:mapping:info**: Shows basic information about all mapped documents;
* **doctrine:phpcr:migrator:migrate**: Migrates PHPCR data;
* **doctrine:phpcr:node-type:list**: List all available node types in the repository;
* **doctrine:phpcr:node-type:register**: Register node types in the PHPCR repository;
* **doctrine:phpcr:node:dump**: Dump subtrees of the content repository;
* **doctrine:phpcr:node:move**: Moves a node from one path to another;
* **doctrine:phpcr:node:remove**: Remove content from the repository;
* **doctrine:phpcr:node:touch**: Create or modify a node;
* **doctrine:phpcr:nodes:update**: Command to manipulate the nodes in the workspace;
* **doctrine:phpcr:repository:init**: Initialize the PHPCR repository;
* **doctrine:phpcr:workspace:create**: Create a workspace in the configured repository;
* **doctrine:phpcr:workspace:export**: Export nodes from the repository,
either to the JCR system view format or the document view format;
* **doctrine:phpcr:workspace:import**: Import xml data into the repository,
either in JCR system view format or arbitrary xml;
* **doctrine:phpcr:workspace:list**: List all available workspaces in the configured repository;
* **doctrine:phpcr:workspace:purge**: Remove all nodes from a workspace;
* **doctrine:phpcr:workspace:query**: Execute a JCR SQL2 statement.
.. note::
To use the ``doctrine:phpcr:fixtures:load`` command, you additionally need
to install the `DoctrineFixturesBundle`_ and its dependencies. See
:ref:`phpcr-odm-repository-fixtures` for how to use fixtures.
Some Example Command Runs
~~~~~~~~~~~~~~~~~~~~~~~~~
Running `SQL2 queries`_ against the repository:
.. code-block:: bash
$ php bin/console doctrine:phpcr:workspace:query "SELECT title FROM [nt:unstructured] WHERE NAME() = 'home'"
Dumping nodes under ``/cms/simple`` including their properties:
.. code-block:: bash
$ php bin/console doctrine:phpcr:node:dump /cms/simple --props
.. _phpcr-odm-backup-restore:
Simple Backup and Restore
~~~~~~~~~~~~~~~~~~~~~~~~~
To export all repository data into a file, you can use:
.. code-block:: bash
$ php bin/console doctrine:phpcr:workspace:export --path /cms /path/to/backup.xml
.. note::
You always want to specify a path to export. Without any path you will
export the root node of the repository, which will be imported later as
``jcr:root``.
To restore this backup you can run:
.. code-block:: bash
$ php bin/console doctrine:phpcr:workspace:import /path/to/backup.xml
Note that you can also export and import parts of your repository by choosing a
different path on export and specifying the ``--parentpath`` option to the
import.
If you already have data in your repository that you want to replace, you can
remove the target node first:
.. code-block:: bash
$ php bin/console doctrine:phpcr:node:remove /cms
Read On
-------
* :doc:`models`
* :doc:`events`
* :doc:`forms`
* :doc:`fixtures_initializers`
* :doc:`multilang`
* :doc:`multiple_sessions`
* :doc:`configuration`
.. _`PHPCR-ODM documentation`: https://www.doctrine-project.org/projects/doctrine-phpcr-odm/en/latest/index.html
.. _`DoctrinePHPCRBundle`: https://github.com/doctrine/DoctrinePHPCRBundle
.. _`Symfony Doctrine documentation`: https://symfony.com/doc/current/doctrine.html
.. _`Jackalope`: http://jackalope.github.io/
.. _`the PHPCR website`: https://phpcr.github.io/
.. _`bug in libxml`: https://bugs.php.net/bug.php?id=36501
.. _`with composer`: https://getcomposer.org
.. _`doctrine/phpcr-bundle`: https://packagist.org/packages/doctrine/phpcr-bundle
.. _`custom node type`: https://github.com/doctrine/phpcr-odm/wiki/Custom-node-type-phpcr%3Amanaged
.. _`DoctrineMigrationsBundle`: https://symfony.com/bundles/DoctrineMigrationsBundle/current/index.html
.. _`DoctrineFixturesBundle`: https://symfony.com/bundles/DoctrineFixturesBundle/current/index.html
.. _`SQL2 queries`: http://www.h2database.com/jcr/grammar.html

342
doc/models.rst Normal file
View File

@@ -0,0 +1,342 @@
.. index::
single: PHPCR; Bundles
single: DoctrinePHPCRBundle
Modeling Data with PHPCR-ODM
============================
The Doctrine PHPCR-ODM is a doctrine object-mapper on top of the
`PHP Content Repository`_ (PHPCR), which is a PHP adaption of the
`JSR-283 specification`_. The most important feature of PHPCR is the tree
structure to store the data. All data is stored in items of a tree, called
nodes. You can think of this like a file system, that makes it perfect to use
in a CMS.
On top of the tree structure, PHPCR also adds features like searching,
versioning and access control.
Doctrine PHPCR-ODM has the same API as the other Doctrine libraries, like the
`Doctrine ORM`_. The Doctrine PHPCR-ODM adds another great feature to PHPCR:
multi-language support.
A Simple Example: A Task
------------------------
The easiest way to get started with the PHPCR-ODM is to see it in action. In
this section, you are going to create a ``Task`` object and learn how to
persist it.
Creating a Document Class
~~~~~~~~~~~~~~~~~~~~~~~~~
Without thinking about Doctrine or PHPCR-ODM, you can create a ``Task`` object
in PHP::
// src/App/Document/Task.php
namespace use App\Document;
class Task
{
protected $description;
protected $done = false;
}
This class - often called a "document" in PHPCR-ODM, meaning *a basic class
that holds data* - is simple and helps fulfill the business requirement of
needing tasks in your application. This class can't be persisted to
Doctrine PHPCR-ODM yet - it's just a simple PHP class.
.. note::
A Document is analogous to the term ``Entity`` employed by the Doctrine
ORM. To have the mapping happen automatically, place your documents in the
``Document`` namespace within your application.
Add Mapping Information
~~~~~~~~~~~~~~~~~~~~~~~
Doctrine allows you to work with PHPCR in a much more interesting way than
just fetching data back and forth as an array. Instead, Doctrine allows you to
persist entire objects to PHPCR and fetch entire *objects* out of PHPCR.
This works by mapping a PHP class and its properties to the PHPCR tree.
For Doctrine to be able to do this, you just have to create "metadata", or
configuration that tells Doctrine exactly how the ``Task`` document and its
properties should be *mapped* to PHPCR. This metadata can be specified in a
number of different formats including YAML, XML or directly inside the ``Task``
class via attributes:
.. configuration-block::
.. code-block:: php
// src/App/Document/Task.php
namespace App\Document;
use Doctrine\ODM\PHPCR\Mapping\Attributes as PHPCR;
#[PHPCR\Document]
class Task
{
#[PHPCR\Id]
private $id;
#[PHPCR\Field(type: 'string')]
private $description;
#[PHPCR\Field(type: 'boolean')]
private $done = false;
#[PHPCR\ParentDocument]
private $parentDocument;
}
.. code-block:: yaml
# src/App/Resources/config/doctrine/Task.phpcr.yml
App\Document\Task:
id: id
fields:
description: string
done: boolean
parent_document: parentDocument
.. code-block:: xml
<!-- src/App/Resources/config/doctrine/Task.phpcr.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<doctrine-mapping
xmlns="http://doctrine-project.org/schemas/phpcr-odm/phpcr-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/phpcr-odm/phpcr-mapping
https://github.com/doctrine/phpcr-odm/raw/master/doctrine-phpcr-odm-mapping.xsd"
>
<document name="App\Document\Task">
<id name="id" />
<field name="description" type="string" />
<field name="done" type="boolean" />
<parent-document name="parentDocument" />
</document>
</doctrine-mapping>
After this, you have to create getters and setters for the properties.
.. note::
This Document uses the parent document and a node name to determine its
position in the tree. Because there isn't any name set, it is generated
automatically. If you want to use a specific node name, such as a
slugified version of the title, you need to add a property mapped as
``Nodename``.
A Document must have an id property. This represents the full path (parent
path + name) of the Document. This will be set by Doctrine by default and
it is not recommend to use the id to determine the location of a Document.
For more information about identifier generation strategies, refer to the
`doctrine documentation`_
.. tip::
You may want to implement ``Doctrine\ODM\PHPCR\HierarchyInterface`` to
expose the hierarchy in a standardized way.
.. seealso::
You can also check out Doctrine's `Basic Mapping Documentation`_ for all
details about mapping information. If you use attributes, you'll need to
prepend all attributes with ``PHPCR\``, which is the name of the imported
namespace (e.g. ``#[PHPCR\Document(..)]``), this is not shown in Doctrine's
documentation. You'll also need to include the
``use Doctrine\ODM\PHPCR\Mapping\Attributes as PHPCR;`` statement to
import the PHPCR attributes prefix.
Persisting Documents to PHPCR
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Now that you have a mapped ``Task`` document, complete with getter and setter
methods, you are ready to persist data to PHPCR. For a simple example, lets do
this from inside a controller::
// src/App/Controller/DefaultController.php
// ...
use App\Document\Task;
use Doctrine\ODM\PHPCR\DocumentManagerInterface;
use Symfony\Component\HttpFoundation\Response;
// ...
public function createAction(DocumentManagerInterface $documentManager)
{
$rootTask = $documentManager->find(null, '/tasks');
$task = new Task();
$task->setDescription('Finish CMF project');
$task->setParentDocument($rootTask);
$documentManager->persist($task);
$documentManager->flush();
return new Response('Created task "'.$task->getDescription().'"');
}
Take a look at the previous example in more detail:
* **line 8** We use symfony controller injection with autowiring to get the
*document manager*. This service is responsible for storing and fetching
objects to and from PHPCR.
* **line 10** This line loads the root document for the tasks, as each PHPCR
document needs to have a parent. To create this root document, you can
configure a :ref:`Repository Initializer <phpcr-odm-repository-initializers>`,
which will be executed when running ``doctrine:phpcr:repository:init``.
* **lines 12-14** In this section, you instantiate and work with the ``$task``
object like any other, normal PHP object.
* **line 16** The ``persist()`` method tells Doctrine to "manage" the ``$task``
object. This does not actually cause a query to be made to PHPCR (yet).
* **line 20** When the ``flush()`` method is called, Doctrine looks through all
of the objects that it is managing to see if they need to be stored to PHPCR.
In this example, the ``$task`` object has not been saved yet, so the document
manager makes a query to PHPCR to add it.
When creating or updating objects, the workflow is always the same. In the
next section, you'll see how Doctrine is smart enough to update documents if
they already exist in PHPCR.
Fetching Objects from PHPCR
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Fetching an object back out of PHPCR is even easier. For example, suppose
you've configured a route to display a specific task by name::
use App\Document\Task;
use Doctrine\ODM\PHPCR\DocumentManagerInterface;
public function showAction(DocumentManagerInterface $documentManager, $name)
{
$repository = $documentManager->getRepository(Task::class);
$task = $repository->find('/tasks/'.$name);
if (!$task) {
throw $this->createNotFoundException('No task found with name '.$name);
}
return new Response('['.($task->isDone() ? 'x' : ' ').'] '.$task->getDescription());
}
To retrieve objects from the document repository using both the ``find`` and
``findMany`` methods and all helper methods of a class-specific repository. In
PHPCR, it's often unknown for developers which node has the data for a specific
document, in that case you should use the document manager to find the nodes
(for instance, when you want to get the root document). In example above, we
know they are ``Task`` documents and so we can use the repository.
The repository contains all sorts of helpful methods::
// query by the id (full path)
$task = $repository->find($id);
// query for one task matching be name and done
$task = $repository->findOneBy(['name' => 'foo', 'done' => false]);
// query for all tasks matching the name, ordered by done
$tasks = $repository->findBy(
['name' => 'foo'],
['done' => 'ASC']
);
.. tip::
If you use the repository class, you can also create a custom repository
for a specific document. This helps with "Separation of Concern" when using more
complex queries. This is similar to how it's done in Doctrine ORM, for
more information read "`Custom Repository Classes`_" in the core
documentation.
.. tip::
You can also query objects by using the Query Builder provided by
Doctrine PHPCR-ODM. For more information, read
`the QueryBuilder documentation`_.
Updating an Object
~~~~~~~~~~~~~~~~~~
Once you've fetched an object from Doctrine, updating it is easy. Suppose you
have a route that maps a task ID to an update action in a controller::
use App\Document\Task;
use Doctrine\ODM\PHPCR\DocumentManagerInterface;
public function updateAction(DocumentManagerInterface $documentManager, $name)
{
$repository = $documentManager->getRepository(Task::class);
$task = $repository->find('/tasks/'.$name);
if (!$task) {
throw $this->createNotFoundException('No task found for name '.$name);
}
if (!$task->isDone()) {
$task->setDone(true);
}
$documentManager->flush();
return new Response('[x] '.$task->getDescription());
}
Updating an object involves just three steps:
#. fetching the object from Doctrine;
#. modifying the object;
#. calling ``flush()`` on the document manager
Notice that calling ``$documentManger->persist($task)`` isn't necessary.
Recall that this method simply tells Doctrine to manage or "watch" the
``$task`` object. In this case, since you fetched the ``$task`` object from
Doctrine, it's already managed.
Deleting an Object
~~~~~~~~~~~~~~~~~~
Deleting an object is very similar, but requires a call to the ``remove()``
method of the document manager after you fetched the document from PHPCR::
$documentManager->remove($task);
$documentManager->flush();
As you might expect, the ``remove()`` method notifies Doctrine that you'd like
to remove the given document from PHPCR. The actual delete operation
however, is not actually executed until the ``flush()`` method is called.
Summary
-------
With Doctrine, you can focus on your objects and how they're useful in your
application and worry about database persistence second. This is because
Doctrine allows you to use any PHP object to hold your data and relies on
mapping metadata information to map an object's data to a particular database
table.
And even though Doctrine revolves around a simple concept, it's incredibly
powerful, allowing you to `create complex queries`_ and
:doc:`subscribe to events <events>` that allow you to take different actions as
objects go through their persistence lifecycle.
.. _`PHP Content Repository`: http://phpcr.github.io/
.. _`JSR-283 specification`: https://jcp.org/en/jsr/detail?id=283
.. _`Doctrine ORM`: https://symfony.com/doc/current/doctrine.html
.. _`doctrine documentation`: http://docs.doctrine-project.org/projects/doctrine-phpcr-odm/en/latest/reference/basic-mapping.html#basicmapping-identifier-generation-strategies
.. _`Basic Mapping Documentation`: http://docs.doctrine-project.org/projects/doctrine-phpcr-odm/en/latest/reference/basic-mapping.html
.. _`the QueryBuilder documentation`: http://docs.doctrine-project.org/projects/doctrine-phpcr-odm/en/latest/reference/query-builder.html
.. _`create complex queries`: http://docs.doctrine-project.org/projects/doctrine-phpcr-odm/en/latest/reference/query-builder.html
.. _`Custom Repository Classes`: https://symfony.com/doc/current/doctrine/repository.html

197
doc/multilang.rst Normal file
View File

@@ -0,0 +1,197 @@
.. index::
single: Multi-Language; DoctrinePHPCRBundle
Doctrine PHPCR-ODM Multi-Language Support
=========================================
PHPCR-ODM can handle translated documents. All translations of the same
document are considered the same document. Only one language version can be
loaded at the same time.
Note that the CMF routing component does not use translated routes but has a
`separate route per language`_.
To use the multi-language features of PHPCR-ODM you need to enable locales in
the configuration.
Translation Configuration
-------------------------
To use translated documents, you need to configure the available languages:
.. configuration-block::
.. code-block:: yaml
# app/config/config.yml
doctrine_phpcr:
odm:
# ...
locales:
en: [de, fr]
de: [en, fr]
fr: [en, de]
locale_fallback: hardcoded
default_locale: fr
.. code-block:: xml
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services">
<config xmlns="http://doctrine-project.org/schema/symfony-dic/odm/phpcr">
<odm locale-fallback="hardcoded">
<!-- ... -->
<locale name="en">
<fallback>de</fallback>
<fallback>fr</fallback>
</locale>
<locale name="de">
<fallback>en</fallback>
<fallback>fr</fallback>
</locale>
<locale name="fr">
<fallback>en</fallback>
<fallback>de</fallback>
</locale>
<default_locale>fr</default_locale>
</odm>
</config>
</container>
.. code-block:: php
// app/config/config.php
$container->loadFromExtension('doctrine_phpcr', [
'odm' => [
// ...
'locales' => [
'en' => ['de', 'fr'],
'de' => ['en', 'fr'],
'fr' => ['en', 'de'],
],
'locale_fallback' => 'hardcoded',
'default_locale' => 'fr',
]
]);
The ``locales`` is a list of alternative locales to look up if a document
is not translated to the requested locale.
The default locale is used for the standard locale chooser strategy and
hence will be the default locale in the document manager. Specifying the
default locale is optional. If you do not specify a default locale then the
first locale listed is used as the default locale.
This bundle provides a request listener that gets activated when any locales
are configured. This listener updates PHPCR-ODM to use the locale Symfony
determined for this request, if that locale is in the list of keys defined
under ``locales``.
Fallback strategies
~~~~~~~~~~~~~~~~~~~
There are several strategies to adjust the fallback order for the selected
locale based on the accepted languages of the request (determined by Symfony
from the ``Accept-Language`` HTML header). All of them will never add any
locales that where not configured in the ``locales`` to avoid a request
injecting unexpected things into your repository:
* ``hardcoded``: This strategy does not update the fallback order from
the request;
* ``replace``: takes the accepted locales from the request and updates the
fallback order with them, removing any locales not found in the request;
* ``merge``: does the same as ``replace`` but then adds locales not found in
the request but on the ``locales`` configuration back to the end of the
fallback list. This reorders the locales without losing any of them. This is
the default strategy.
Translated documents
--------------------
To make a document translated, you need to define the ``translator`` attribute
on the document mapping, and you need to map the ``locale`` field. Then you can
use the ``translated`` attribute on all fields that should be different
depending on the locale.
.. configuration-block::
.. code-block:: php
// src/App/Documents/Article.php
namespace App\Documents\Article;
use Doctrine\ODM\PHPCR\Mapping\Attributes as PHPCR;
#[PHPCR\Document(translator: 'attribute')]
class Article
{
/**
* The language this document currently is in
*/
#[PHPCR\Locale]
private $locale;
/**
* Untranslated property
*/
#[PHPCR\Date]
private $publishDate;
/**
* Translated property
*/
#[PHPCR\Field(type: 'string', translated: true)]
private $topic;
/**
* Language specific image
*/
#[PHPCR\Binary(translated: true)]
private $image;
}
.. code-block:: xml
<doctrine-mapping>
<document class="App\Documents\Article"
translator="attribute">
<locale fieldName="locale" />
<field fieldName="publishDate" type="date" />
<field fieldName="topic" type="string" translated="true" />
<field fieldName="image" type="binary" translated="true" />
</document>
</doctrine-mapping>
.. code-block:: yaml
App\Documents\Article:
translator: attribute
locale: locale
fields:
publishDate:
type: date
topic:
type: string
translated: true
image:
type: binary
translated: true
Unless you explicitly interact with the multi-language features of PHPCR-ODM,
documents are loaded in the request locale and saved in the locale they where
loaded. (This could be a different locale, if the PHPCR-ODM did not find the
requested locale and had to fall back to an alternative locale.)
.. tip::
For more information on multilingual documents, see the
`PHPCR-ODM documentation on multi-language`_.
.. _`PHPCR-ODM documentation on multi-language`: http://docs.doctrine-project.org/projects/doctrine-phpcr-odm/en/latest/reference/multilang.html
.. _`separate route per language`: https://symfony.com/bundles/CMFRoutingBundle/current/routing-component/dynamic.html

348
doc/multiple_sessions.rst Normal file
View File

@@ -0,0 +1,348 @@
.. index::
single: Multisession; DoctrinePHPCRBundle
Configuring multiple sessions for PHPCR-ODM
===========================================
If you need more than one PHPCR backend, you can define ``sessions`` as child
of the ``session`` information. Each session has a name and the configuration
following the same schema as what is directly in ``session``. You can also
overwrite which session to use as ``default_session``. Once you have multiple
sessions, you can also configure multiple document managers with those
sessions.
.. tip::
Autowiring always gives you the default session and the default document
manager. When working with multiple sessions and managers, you need to
explicitly specify the services. For the document managers, you can also
go through the manager registry (see at the end of this page).
.. _bundles-phpcr-odm-multiple-phpcr-sessions:
Multiple PHPCR Sessions
-----------------------
.. configuration-block::
.. code-block:: yaml
# app/config/config.yml
doctrine_phpcr:
session:
default_session: ~
sessions:
<name>:
workspace: ... # Required
username: ~
password: ~
backend:
# ...
options:
# ...
.. code-block:: xml
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services">
<config xmlns="http://doctrine-project.org/schema/symfony-dic/odm/phpcr">
<session default-session="null">
<!-- workspace: Required -->
<session name="<name>"
workspace="..."
username="null"
password="null"
>
<backend>
<!-- ... -->
</backend>
<option>
<!-- ... -->
</option>
</session>
</session>
</config>
</container>
.. code-block:: php
// app/config/config.php
$container->loadFromExtension('doctrine_phpcr', [
'session' => [
'default_session' => null,
'sessions' => [
'<name>' => [
'workspace' => '...', // Required
'username' => null,
'password' => null,
'backend' => [
// ...
],
'options' => [
// ...
],
],
],
],
]);
Multiple Document Managers
--------------------------
If you are using the ODM, you will also want to configure multiple document
managers.
Inside the odm section, you can add named entries in the
``document_managers``. To use the non-default session, specify the session
attribute.
.. configuration-block::
.. code-block:: yaml
# app/config/config.yml
odm:
default_document_manager: ~
document_managers:
<name>:
session: <sessionname>
# ... configuration as above
.. code-block:: xml
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services">
<config xmlns="http://doctrine-project.org/schema/symfony-dic/odm/phpcr">
<odm default-document-manager="null">
<document-manager
name="<name>"
session="<sessionname>"
>
<!-- ... configuration as above -->
</document-manager>
</odm>
</config>
</container>
.. code-block:: php
// app/config/config.php
$container->loadFromExtension('doctrine_phpcr', [
'odm' => [
'default_document_manager' => null,
'document_managers' => [
'<name>' => [
'session' => '<sessionname>',
// ... configuration as above
],
],
],
]);
Bringing it all together
------------------------
The following full example uses the default manager for ``AppBundle``
and the documents provided by the CMF. Additionally, it has a website
and DMS manager that connects to the Jackrabbit of Magnolia CMS. That
manager looks for models in the MagnoliaBundle.
.. configuration-block::
.. code-block:: yaml
doctrine_phpcr:
# configure the PHPCR sessions
session:
sessions:
default:
backend: "%phpcr_backend%"
workspace: "%phpcr_workspace%"
username: "%phpcr_user%"
password: "%phpcr_pass%"
website:
backend:
type: jackrabbit
url: "%magnolia_url%"
workspace: website
username: "%magnolia_user%"
password: "%magnolia_pass%"
dms:
backend:
type: jackrabbit
url: "%magnolia_url%"
workspace: dms
username: "%magnolia_user%"
password: "%magnolia_pass%"
# enable the ODM layer
odm:
auto_generate_proxy_classes: "%kernel.debug%"
document_managers:
default:
session: default
mappings:
AppBundle: ~
CmfContentBundle: ~
CmfMenuBundle: ~
CmfRoutingBundle: ~
website:
session: website
configuration_id: magnolia.odm_configuration
mappings:
MagnoliaBundle: ~
dms:
session: dms
configuration_id: magnolia.odm_configuration
mappings:
MagnoliaBundle: ~
.. code-block:: xml
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services">
<config xmlns="http://doctrine-project.org/schema/symfony-dic/odm/phpcr">
<session>
<session name="default"
backend="%phpcr_backend%"
workspace="%phpcr_workspace%"
username="%phpcr_user%"
password="%phpcr_pass%"
/>
<session name="website"
workspace="website"
username="%magnolia_user%"
password="%magnolia_pass%"
>
<backend type="jackrabbit" url="%magnolia_url%"/>
</session>
<session name="dms"
workspace="dms"
username="%magnolia_user%"
password="%magnolia_pass%"
>
<backend type="jackrabbit" url="%magnolia_url%"/>
</session>
</session>
<!-- enable the ODM layer -->
<odm auto-generate-proxy-classes="%kernel.debug%">
<document-manager
name="default"
session="default"
>
<mapping name="AppBundle" />
<mapping name="CmfContentBundle" />
<mapping name="CmfMenuBundle" />
<mapping name="CmfRoutingBundle" />
</document-manager>
<document-manager
name="website"
session="website"
configuration-id="magnolia.odm_configuration"
>
<mapping name="MagnoliaBundle" />
</document-manager>
<document-manager
name="dms"
session="dms"
configuration-id="magnolia.odm_configuration"
>
<mapping name="MagnoliaBundle" />
</document-manager>
</odm>
</config>
</container>
.. code-block:: php
// app/config/config.php
$container->loadFromExtension('doctrine_phpcr', [
'session' => [
'sessions' => [
'default' => [
'backend' => '%phpcr_backend%',
'workspace' => '%phpcr_workspace%',
'username' => '%phpcr_user%',
'password' => '%phpcr_pass%',
],
'website' => [
'backend' => [
'type' => 'jackrabbit',
'url' => '%magnolia_url%',
],
'workspace' => 'website',
'username' => '%magnolia_user%',
'password' => '%magnolia_pass%',
],
'dms' => [
'backend' => [
'type' => 'jackrabbit',
'url' => '%magnolia_url%',
],
'workspace' => 'dms',
'username' => '%magnolia_user%',
'password' => '%magnolia_pass%',
],
],
],
// enable the ODM layer
'odm' => [
'auto_generate_proxy_classes' => '%kernel.debug%',
'document_managers' => [
'default' => [
'session' => 'default',
'mappings' => [
'AppBundle' => null,
'CmfContentBundle' => null,
'CmfMenuBundle' => null,
'CmfRoutingBundle' => null,
],
],
'website' => [
'session' => 'website',
'configuration_id' => 'magnolia.odm_configuration',
'mappings' => [
'MagnoliaBundle' => null,
],
],
'dms' => [
'session' => 'dms',
'configuration_id' => 'magnolia.odm_configuration',
'mappings' => [
'MagnoliaBundle' => null,
],
],
],
],
]);
You can access the managers through the manager registry available in the
service ``Doctrine\Bundle\PHPCRBundle\ManagerRegistry``::
use Doctrine\Bundle\PHPCRBundle\ManagerRegistry;
/** @var $container \Symfony\Component\DependencyInjection\ContainerInterface */
// get the named manager from the registry
$dm = $container->get(ManagerRegistry::class)->getManager('website');
// get the manager for a specific document class
$dm = $container->get(ManagerRegistry::class)->getManagerForClass('CmfContentBundle:StaticContent');
Additionally, each manager is available as a service in the DI container.
The service name pattern is ``doctrine_phpcr.odm.<name>_document_manager`` so for
example the website manager is called
``doctrine_phpcr.odm.website_document_manager``.