mirror of
https://github.com/doctrine/DoctrinePHPCRBundle.git
synced 2026-03-23 22:32:20 +01:00
resurrect documentation from the old symfony-cmf-docs repository
This commit is contained in:
14
.doctrine-project.json
Normal file
14
.doctrine-project.json
Normal 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
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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
720
doc/configuration.rst
Normal 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
101
doc/events.rst
Normal 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
|
||||
306
doc/fixtures_initializers.rst
Normal file
306
doc/fixtures_initializers.rst
Normal 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
183
doc/forms.rst
Normal 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
14
doc/index.rst
Normal 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
568
doc/introduction.rst
Normal 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
342
doc/models.rst
Normal 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
197
doc/multilang.rst
Normal 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
348
doc/multiple_sessions.rst
Normal 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``.
|
||||
Reference in New Issue
Block a user