You are browsing a version that is no longer maintained.

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)

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.

1require: { ... "jackalope/jackalope-doctrine-dbal": "1.2.*", "doctrine/phpcr-odm": "1.2.*", "doctrine/phpcr-bundle": "1.2.*", ... }
2
3
4
5
6
7

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 configuration reference.

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:

1# app/config/parameters.yml parameters: database_driver: pdo_mysql database_host: localhost database_name: test_project database_user: root database_password: password # ...
2
3
4
5
6
7
8
9
  • YAML
    1# app/config/config.yml doctrine: dbal: driver: "%database_driver%" host: "%database_host%" dbname: "%database_name%" user: "%database_user%" password: "%database_password%"
    2
    3
    4
    5
    6
    7
    8
  • XML
    1<!-- 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>
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
  • PHP
    1// app/config/config.php $configuration->loadFromExtension('doctrine', [ 'dbal' => [ 'driver' => '%database_driver%', 'host' => '%database_host%', 'dbname' => '%database_name%', 'user' => '%database_user%', 'password' => '%database_password%', ], ]);
    2
    3
    4
    5
    6
    7
    8
    9
    10

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:

  • YAML
    1# 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
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
  • XML
    1<!-- 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>
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
  • PHP
    1// 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', ], ]);
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

Now make sure the database exists and initialize it:

# without Doctrine ORM
php bin/console doctrine:database:create
php bin/console doctrine:phpcr:init:dbal

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.

# Using Doctrine ORM
php bin/console doctrine:database:create
php bin/console doctrine:schema:create

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.

  • YAML
    1# 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
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
  • XML
    1<!-- 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>
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
  • PHP
    1// 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, ], ], ], ]);
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

When auto_mapping is enabled, bundles will be automatically loaded and attempted to resolve mappings

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 Configuration Reference, 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:

$ 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:

  • YAML
    1# app/config/config.yml doctrine_phpcr: session: backend: # ... logging: true profiling: true
    2
    3
    4
    5
    6
    7
  • XML
    1<!-- 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>
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
  • PHP
    1// app/config/config.yml $container->loadFromExtension('doctrine_phpcr', [ 'session' => [ 'backend' => [ // ... 'logging' => true, 'profiling' => true, ], ], ]);
    2
    3
    4
    5
    6
    7
    8
    9
    10

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.

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.

To use the doctrine:phpcr:fixtures:load command, you additionally need to install the DoctrineFixturesBundle and its dependencies. See Maintaining Data in the Repository for how to use fixtures.

Some Example Command Runs

Running SQL2 queries against the repository:

$ php bin/console doctrine:phpcr:workspace:query "SELECT title FROM [nt:unstructured] WHERE NAME() = 'home'"

Dumping nodes under /cms/simple including their properties:

$ php bin/console doctrine:phpcr:node:dump /cms/simple --props

Simple Backup and Restore

To export all repository data into a file, you can use:

$ php bin/console doctrine:phpcr:workspace:export --path /cms /path/to/backup.xml

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:

$ 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:

$ php bin/console doctrine:phpcr:node:remove /cms