El DoctrinePHPCRBundle proporciona integración con el repositorio de contenido PHP y opcionalmente con el PHPCR-ODM de Doctrine para proporcionar el gestor de documentos ODM en Symfony.
Fuera de la caja, este paquete apoya las siguientes implementaciones PHPCR:
Truco
Esta referencia sólo explica la integración de Symfony2 con PHPCR y PHPCR-ODM. Para aprender cómo utilizar PHPCR ve al sitio web de PHPCR y para la documentación del PHPCR-ODM de Doctrine .
Este paquete está basado en el AbstractDoctrineBundle y por lo tanto es similar a la configuración de los paquetes ORM y MongoDB de Doctrine.
Truco
Si sólo quieres utilizar el PHPCR sencillo sin el PHPCR-ODM, sencillamente no configures la sección odm para evitar que cargue los servicios. Ten en cuenta que muchos paquetes predefinidos del CMF usan documentos PHPCR-ODM y por ello necesitas habilitar el ODM.
La sesión necesita que especifiques una implementación PHPCR en la sección backend para el campo type, junto con opciones de configuración al arranque de la implementación. Actualmente apoyamos jackrabbit, doctrinedbal y midgard2. Independientemente de la interfaz de administración, cada sesión PHPCR necesita un espacio de trabajo, nombre de usuario y contraseña.
Truco
Cada implementación de PHPCR debería proporcionar el espacio de trabajo llamado «default», pero puedes elegir uno diferente. Existe la orden doctrine:phpcr:workspace:create para iniciar un nuevo espacio de trabajo. See also Servicios.
El nombre de usuario y contraseña que especifiques aquí son los utilizados en la capa PHPCR en PHPCR\SimpleCredentials. Normalmente serán diferentes del nombre de usuario y contraseña utilizados por Midgard2 o el DBAL de Doctrine para conectar al RDBMS subyacente donde de hecho se almacenan los datos.
Si estás utilizando una de las interfaces de administración de Jackalope, también puedes especificar opciones. Estas serán puestas en la sesión de Jackalope. Actualmente esto se puede ajustar a nodos prerecuperados poniendo jackalope.fetch_depth a algo más grande que 0.
# app/config/config.yml
doctrine_phpcr:
session:
backend:
# ve abajo cómo configurar la interfaz de administración que elejiste
workspace: default
username: admin
password: admin
## ajusta opciones para jackrabbit y doctrinedbal (todas las versiones de jackalope)
# options:
# 'jackalope.fetch_depth': 1
Es la única configuración requerida para instalar el Jackrabbit de apache (ve instalando Jackrabbit).
La configuración necesita que el parámetro url apunte a tu jackrabbit. Además puedes afinar algunas otras opciones específicas de jackrabbit, por ejemplo para utilizarlas en la configuración de una carga balanceada o para fallar temprano y aminorar el costo de algunos viajes de ida y vuelta a la interfaz de administración.
# app/config/config.yml
doctrine_phpcr:
session:
backend:
type: jackrabbit
url: http://localhost:8080/server/
## únicamente jackrabbit, opcional. ve https://github.com/jackalope/jackalope/blob/master/src/Jackalope/RepositoryFactoryJackrabbit.php
# default_header: ...
# expect: 'Esperaba: 100-continue'
# habilita si de cualquier manera quieres tener una excepción si
# falla el incio de sesión PHPCR
# check_login_on_server: false
# habilita si experimentas fallos de segmentación mientras
# trabajas con datos binarios en documentos
# disable_stream_wrapper: true
# habilita si no quieres usar transacciones y tampoco quieres
# que el odm use transacciones automáticamente, es altamente
# recomendable NO deshabilitar las transacciones
# disable_transactions: true
Este tipo usa Jackalope con una abstracción en la capa de transporte de base de datos de Doctrine para proporcionar PHPCR sin ningún requisito de instalación más allá de cualquiera de los RDBMS apoyados por Doctrine.
Necesitas configurar una conexión de Doctrine según el DBAL elejido en la documentación de Doctrine en Symfony2.
# app/config/config.yml
doctrine_phpcr:
session:
backend:
type: doctrinedbal
connection: doctrine.dbal.default_connection
# habilita si quieres tener una excepción inmediatamente si falla
# el inicio de sesión PHPCR
# check_login_on_server: false
# habilita si experimentas fallos de segmentación mientras
# trabajas con datos binarios en documentos
# disable_stream_wrapper: true
# habilita si no quieres usar transacciones y tampoco quieres
# que el odm use transacciones automáticamente, es altamente
# recomendable NO deshabilitar las transacciones
# disable_transactions: true
Una vez configurada la conexión, puedes crear la base de datos y debes iniciar la base de datos con la orden doctrine:phpcr:init:dbal.
app/console doctrine:database:create
app/console doctrine:phpcr:init:dbal
Truco
Naturalmente, también puedes utilizar una diferente conexión en vez de la predefinida. Es recomendable utilizar una conexión independiente para una base de datos separada si también Doctrine usa el acceso a datos del ORM o DBAL directamente, en lugar de mezclar este dato con las tablas generadas por jackalope-doctrine-dbal. Si tienes una conexión separada, necesitas pasar el nombre de la conexión alterna a la orden doctrine:database:create con la opción --connection. Para las ordenes PHPCR de Doctrine, este parámetro no es necesario al configurar la conexión a utilizar.
Midgard2 es una aplicación que proporciona una extensión PHP compilada. Esta implementa la API de PHPCR en lo alto de un RDBMS estándar.
To use the Midgard2 PHPCR provider, you must have both the midgard2 PHP extension and the midgard/phpcr package installed. The settings here correspond to Midgard2 repository parameters as explained in the getting started document.
La sesión de configuración de la interfaz de administración es la siguiente:
# app/config/config.yml
doctrine_phpcr:
session:
backend:
type: midgard2
db_type: MySQL
db_name: midgard2_test
db_host: "0.0.0.0"
db_port: 3306
db_username: ""
db_password: ""
db_init: true
blobdir: /tmp/cmf-blobs
Para más información, por favor, ve la documentación oficial del PHPCR de Midgard.
Esta sección de configuración gestiona el sistema PHPCR-ODM de Doctrine. Si no configuras ninguna cosa aquí, los servicios ODM no serán cargados.
Si habilitas auto_mapping, puedes colocar tus asociaciones en <Paquete>/Resources/config/doctrine/<Document>.phpcr.xml resp. ...yml para configurar asociaciones a documentos proporcionadas en el directorio <Paquete>/Document. De lo contrario necesitas configurar manualmente la sección de asignaciones.
Si auto_generate_proxy_classes es false, necesitas ejecutar la orden cache:warmup para tener las clases delegadas generadas después de que modificaste un documento. También puedes ajustar cómo y dónde generar las clases delegadas con las opciones proxy_dir y proxy_namespace. Normalmente las predefinidas están bien aquí.
También puedes habilitar el almacenamiento de metadatos en caché.
# app/config/config.yml
doctrine_phpcr:
odm:
configuration_id: ~
auto_mapping: true
mappings:
<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
metadata_cache_driver:
type: array
host: ~
port: ~
instance_class: ~
class: ~
id: ~
Si estás utilizando documentos multilingües, necesitas configurar los idiomas disponibles. Para más información en documentos multilingües, ve la documentación PHPCR-ODM en multilenguaje.
# app/config/config.yml
doctrine_phpcr:
odm:
...
locales:
en: [en, de, fr]
de: [de, en, fr]
fr: [fr, en, de]
Este bloque define el orden de regiones alternativas para ver si un documento no está traducido al idioma requerido.
Si ajustas la ruta a jackrabbit_jar, puedes utilizar la orden de consola doctrine:phpcr:jackrabbit para arrancar y parar el jackrabbit.
Puedes poner a punto la producción de la orden doctrine:phpcr:dump con dump_max_line_length.
# app/config/config.yml
doctrine_phpcr:
jackrabbit_jar: /ruta/a/jackrabbit.jar
dump_max_line_length: 120
Si necesitas más de una interfaz de administración PHPCR, puedes definir sessions como hijo de la información de session. Cada sesión tiene un nombre y configuración que puedes utilizar directamente en session. también puedes sobrescribir qué sesión utilizar como default_session.
# app/config/config.yml
doctrine_phpcr:
session:
default_session: ~
sessions:
<name>:
workspace: ~ # Requerido
username: ~
password: ~
backend:
# como arriba
options:
# como arriba
Si estás utilizando el ODM, también querrás configurar múltiples gestores de documento.
Dentro de la sección odm, puedes añadir entradas nombradas en document_managers. Para utilizar la sesión no predefinida, especifica el atributo session.
odm:
default_document_manager: ~
document_managers:
<name>:
# mismas claves como directamente en odm, ve arriba.
session: <sessionname>
Un ejemplo completo se ve como sigue:
doctrine_phpcr:
# configura las sesiones 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%
# activa la capa ODM
odm:
document_managers:
default:
session: default
mappings:
SandboxMainBundle: ~
SymfonyCmfContentBundle: ~
SymfonyCmfMenuBundle: ~
SymfonyCmfRoutingExtraBundle: ~
website:
session: website
configuration_id: sandbox_magnolia.odm_configuration
mappings:
SandboxMagnoliaBundle: ~
dms:
session: dms
configuration_id: sandbox_magnolia.odm_configuration
mappings:
SandboxMagnoliaBundle: ~
auto_generate_proxy_classes: %kernel.debug%
Truco
Este ejemplo también utiliza diferentes configuraciones par repositorio (ve el atributo repository_id). Este caso se explica en Usando una clase documento personalizada asociada con PHPCR-ODM.
Puedes acceder el servicios PHPCR con esto:
<?php
namespace Acme\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class DefaultController extends Controller
{
public function indexAction()
{
// ManagerRegistry instance with references to all sessions and document manager instances
$registry = $this->container->get('doctrine_phpcr');
// instancia de la sesión PHPCR
$session = $this->container->get('doctrine_phpcr.default_session');
// instancia del gestor del documento ODM de PHPCR
$documentManager = $this->container->get('doctrine_phpcr.odm.default_document_manager');
}
}
You can tag services to listen to Doctrine PHPCR-ODM events. Esto trabaja de la misma manera que en el ORM de Doctrine. Las únicas diferencias son:
You can register for the events as described in the PHPCR-ODM documentation. Or you can tag your services as event listeners resp. event subscribers.
services:
my.listener:
class: Acme\SearchBundle\EventListener\SearchIndexer
tags:
- { name: doctrine_phpcr.event_listener, event: postPersist }
my.subscriber:
class: Acme\SearchBundle\EventSubscriber\MySubscriber
tags:
- { name: doctrine_phpcr.event_subscriber }
Consejo
Doctrine event subscribers (both ORM and PHPCR-ODM) can not return a flexible array of methods to call like the Symfony event subscriber can do. 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.
More information with PHP code examples for the doctrine event system integration is in this Symfony cookbook entry.
The bundle provides a ValidPhpcrOdm constraint validator you can use to check if your document Id or Nodename and Parent fields are correct.
# src/Acme/BlogBundle/Resources/config/validation.yml
Acme\BlogBundle\Entity\Author:
constraints:
- Doctrine\Bundle\PHPCRBundle\Validator\Constraints\ValidPhpcrOdm
// src/Acme/BlogBundle/Entity/Author.php
// ...
use Doctrine\Bundle\PHPCRBundle\Validator\Constraints as OdmAssert;
/**
* @OdmAssert\ValidPhpcrOdm
*/
class Author
{
...
}
<!-- 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="Symfony\Cmf\Bundle\RoutingExtraBundle\Document\Route">
<constraint name="Doctrine\Bundle\PHPCRBundle\Validator\Constraints\ValidPhpcrOdm" />
</class>
</constraint-mapping>
The bundle provides a couple of handy form types for PHPCR and PHPCR-ODM specific cases, along with form type guessers.
The phpcr_odm_image form maps to a document of type Doctrine\ODM\PHPCR\Document\Image and provides a preview of the uploaded image. To use it, you need to include the LiipImagineBundle in your project and define an imagine filter for thumbnails.
This form type is only available if explicitly enabled in your application configuration by defining the imagine section under the odm section with at least enabled: true. You can also configure the imagine filter to use for the preview, as well as additional filters to remove from cache when the image is replaced. If the filter is not specified, it defaults to image_upload_thumbnail.
doctrine_phpcr:
...
odm:
imagine:
enabled: true
# filter: image_upload_thumbnail
# extra_filters:
# - imagine_filter_name1
# - imagine_filter_name2
# Imagine Configuration
liip_imagine:
...
filter_sets:
# define the filter to be used with the image preview
image_upload_thumbnail:
data_loader: phpcr
filters:
thumbnail: { size: [100, 100], mode: outbound }
Then you can add images to document forms as follows:
use Symfony\Component\Form\FormBuilderInterface;
protected function configureFormFields(FormBuilderInterface $formBuilder)
{
$formBuilder
->add('image', 'phpcr_odm_image', array('required' => false))
;
}
Truco
If you set required to true for the image, the user must re-upload a new image each time he edits the form. If the document must have an image, it makes sense to require the field when creating a new document, but make it optional when editing an existing document. We are trying to make this automatic.
Next you will need to add the fields.html.twig template from the DoctrinePHPCRBundle to the form.resources, to actually see the preview of the uploaded image in the backend.
# Twig Configuration
twig:
form:
resources:
- 'DoctrinePHPCRBundle:Form:fields.html.twig'
The document that should contain the Image document has to implement a setter method. To profit from the automatic guesser of the form layer, the name in the form element and this method name have to match:
public function setImage($image)
{
if (!$image) {
// Esto es normal y sucede cuándo ninguna nueva imagen se ha cargado
return;
} elseif ($this->image && $this->image->getFile()) {
// PENDIENTE: necesario hasta que se haya corregidi este fallo en PHPCRODM: https://github.com/doctrine/phpcr-odm/pull/262
$this->image->getFile()->setFileContent($image->getFile()->getFileContent());
} else {
$this->image = $image;
}
}
To delete an image, you need to delete the document containing the image. (There is a proposal to improve the user experience for that in a DoctrinePHPCRBundle issue.)
Nota
There is a doctrine listener to invalidate the imagine cache for the filters you specified. This listener will only operate when an Image is changed in a web request, but not when a CLI command changes images. When changing images with commands, you should handle cache invalidation in the command or manually remove the imagine cache afterwards.
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:
$dataArr = array(
'/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', array(
'choices' => $dataArr,
'referenced_class' => 'Class\Of\My\Referenced\Documents',
))
->end();
Truco
When building an admin interface with Sonata Admin there is also the sonata_type_model that is more powerful, allowing to add to the referenced documents on the fly. Unfortunately it is currently broken.
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.
To use the doctrine:phpcr:fixtures:load command, you additionally need to install the DoctrineFixturesBundle which brings the Doctrine data-fixtures into Symfony2.
Fixtures work the same way they work for Doctrine ORM. You write fixture classes implementing Doctrine\Common\DataFixtures\FixtureInterface. If you place them in <Bundle>DataFixturesPHPCR, they will be auto detected if you specify no path to the fixture loading command.
A simple example fixture class looks like this:
<?php
namespace MyBundle\DataFixtures\PHPCR;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\Common\DataFixtures\FixtureInterface;
class LoadMyData implements FixtureInterface
{
public function load(ObjectManager $manager)
{
// Create and persist your data here...
}
}
For more on fixtures, see the documentation of the DoctrineFixturesBundle.
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. To find out available migrations run:
$ php app/console doctrine:phpcr:migrator
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.
Todas las órdenes sobre el PHPCR van prefijadas con doctrine:phpcr y puedes utilizar el argumento --session para utilizar una sesión distinta a la predefinida si configuraste varias sesiones PHPCR.
Algunas de estas órdenes son específicas a una interfaz de administración o al ODM. Esas órdenes sólo estarán disponibles si tal interfaz de administración está configurada.
Usa app/console help <orden> para ver todas las opciones que tiene cada orden.
Nota
To use the doctrine:phpcr:fixtures:load command, you additionally need to install the DoctrineFixturesBundle and its dependencies. Ve su página de documentación para aprender a utilizar los accesorios.
Si estás utilizando jackalope-jackrabbit, también tienes una orden para arrancar y detener el servidor jackrabbit:
Si estás utilizando jackalope-doctrine-dbal, tienes una orden para iniciar la base de datos:
Ten en cuenta que también puedes utilizar la orden dbal de doctrine para crear la base de datos.
Ejecutando consultas SQL2 contra el repositorio
app/console doctrine:phpcr:query "SELECT title FROM [nt:unstructured] WHERE NAME() = 'home'"
Vertiendo nodos bajo /cms/simple incluyendo sus propiedades
app/console doctrine:phpcr:dump /cms/simple --props