Qu'est-ce que c'est PHPCR?
C'est:
Et c'est quoi un Content Repository?
Un repository de contenu est peut être:
- Un entrepôt de contenu digitale
- Une API pour le gestion, recherche et méthodes d'accès et de modification de contenu
- La façade d'une couche qui est consacre à le stockage et gestion de contenu
Qu'est que je peux metre dans une repositotry de contenu?
- Données structurées (noeuds avec propriétés et enfants)
- Données binaires (image, video, pdf, etc)
Les Méthodes traditionnelles
Filesystems et RDBMS's
Filesystems
-
Bon pour le stockage des fichiers (quelle suprise)
-
Pas concerné avec le stockage de données structurées
-
Super bien pour le stockage des données hiérarchique
RDBMS (e.g. MySQL)
-
Bon pour le stockage de données structurées
-
Excellente pour le integrité des données
-
Pas bon pour le stockage de fichiers
-
Mauvais pour le stockage des données hiérarchique
-
Mauvais pour le stockage des données pas structurées
Meilleur des deux mondes
Content Repository
(source: http://java.dzone.com/articles/java-content-repository-best)
PHPCR <=> JCR
- PHPCR est une implementation de le specification JCR - Java Content Repository
Overview très vite des chapitres
Il y a les chaptitres concernant les suivantes:
- Repository Model
- Connecting
- Reading
- Query
- Export
- Node Type Discovery
- Permissions and Capabilities
- Writing
- Import
- Observation
- Workspace Management
Overview très vite
- Shareable Nodes
- Versioning
- Access Control Management
- Lifecycle Management
- Node Type Management
- Retention and Hold
- Transactions
- Same-name siblings
- Orderable Child Nodes
- Repository Compliance
Il y a beaucoup des choses!
PHPCR
Une implementation de JCR en PHP
- Premier commit Feb 04 2008
- C'est une implementation complet
- Mais il y a des petits changements
Les Implementations Actuel
- Jackalope
- Un genre de "framework" pour les implementations PHPCR
- Jackalope Jackrabbit: Il stock les données sur serveur Apache Jackrabbit en utilisant une implementation PHP du protocol WebDAV/davex.
- Jackalope Doctrine-Dbal: Il utilise le couche d'abstraction BDD Doctrine pour echanger avec n'importe quelle BDD soutenu par Doctrine
Implementations en cours et speculatifs
-
Midgard (déjà commence, dernier commit il y a 6 mois)
-
Jackalope MongoDB (pas fini, dernier commit il y a plus qu'un an)
- Implementation FS + GIT? pour quoi pas..
Deux exemples d'une session
Avec deux implementations different
Exemple Jackalope DBAL
// chaque implementation doit fournir une repository factory
$factory = new \Jackalope\RepositoryFactoryDoctrineDBAL();
$repository = $factory->getRepository();
$credentials = new \PHPCR\SimpleCredentials('admin', 'mypassword');
$session = $repository->login($credentials);
$node = $session->getNode('/hello');
// profit
$children = $node->getNodes(); // return children nodes
foreach ($children as $child) {
$string = $child->getProperty('world');
echo $string;
}
Exemple Jackalope Jackrabbit
// chaque implementation doit fournir une repository factory
$factory = new \Jackalope\RepositoryFactoryJackrabbit();
$repository = $factory->getRepository();
$credentials = new \PHPCR\SimpleCredentials('admin', 'mypassword');
$session = $repository->login($credentials);
$node = $session->getNode('/hello');
// encore de profit
$children = $node->getNodes(); // return children nodes
foreach ($children as $child) {
$string = $child->getProperty('world');
echo $string;
}
RepositoryFactoryJackDoctrineDbal
vs
RepositoryFactoryJackrabbit
Tout le reste est pareil!
La Session
- Le API de session est l'interface primaire pour le repository
- Il faut connecter à le session avant de faire les choses
- Le plus part des operations sont différées jusqu'à ce que l'on appelle la méthode $session->save() (analogue au Doctrine ORM $em->flush())
Le Session
$session = // obtenir le session
$rootNode = $session->getNode('/'); // recuperer le "root node"
$newNode = $rootNode->addNode('foobar'); // creer une nouveau node avec le nom "foobar"
// rename a node\a
$session->move('/foobar', '/barfoo');
// a cet point les changements sont pas encore fait dans la engin de stockage
$session->save(); // pop! c'est fait
Workspaces
- Un Workspace contenant un graph des nœuds
- C'est possible d'avoir plusieurs Workspaces
- Nodes pourrait être cloné entre les Workspaces
- Il y a une semblance avec le concept de branches en GIT
- Par exemple ...
Workspaces
- Un utilisateur a connecte à le BO de votre CMS
- Il y a une article en ligne qui est très importante
- L'utilisateur doit faire les modifs et montrer les modifs à son chef
-
Sans modifier le article en ligne
- Les workspaces permet à l'utilisateur de travailler sur son propre espace
- Avant de "clone" (voir push, publié) son changements à environnement live
Nodes and Properties
- Chaque nœud est attribué d'une path (e.g. /cms/foobar/my-node)
- Nodes contenant les propriétés
- Il y a les propriétés système
- Et les propriétés normale
- Chaque propriété est attribué une type
- Les noms des propriétés peuvent utiliser les Namespaces
- Analogie filesystem
- Dossiers = Nodes
- Fichiers = Properties
Nodes and Properties
Reperesentation en mode ASCII
/ (:root)
node1/ (nt:unstructured)
| - foobar = barfoo (STRING)
| - barfoo = foobar (STRING)
| ChildNode1/ (nt:folder)
| ChildNode2/ (nt:folder)
article/ (mycms:article)
- title: Titre de mon article (STRING)
- content: Ceci est le contenu de mon article (STRING)
- tags: [ tag1, tag2, tag3 ] (STRING[])
comments/ (mycms:comment))
comment1/ (mycms:comment)
Nodes and Properties
Avec les types système
/ (rep:root)
node1/ (nt:unstructured)
| - jcr:primaryType = nt:unstructured
| - jcr:uuid = 842e61c0-09ab-42a9-87c0-308ccc90e6f4 (REFERENCE)
| - jcr:mixinTypes = [ mix:referenceable ] (REFERENCE[])
| - foobar = barfoo
| - barfoo = foobar
article/ (mycms:article)
- jcr:primaryType = mon_type_article (NAME)
- jcr:mixinTypes = [ mix:versionable, mix:lastModified ] (NAME[])
- title: Titre de mon article (STRING)
- content: Ceci est le contenu de mon article (STRING)
- tags: [ tag1, tag2, tag3 ] (STRING[])
comments/ (mycms:comment))
comment1/ (mycms:comment)
References
- Nœuds peuvent être "Referenceable"
- Les nœuds référençables sont attribué une UUID (Universally Unique Identifier, ou identifiant universel unique)
- Ils peuvent être référencé par n'importe quel autre nœuds dans le Repository
- En contraste avec le paradigme typique de RDBMS
- Les contraintes d'intégrité sont garder quand une référence est attribué une statu "STRONG" (en constrast de "WEAK")
References
- Exemple - catégories
- Vous pouvez faire une lien avec une catégorie avec n'importe quelle nœud
- Vous pouvez faire référence à une catégorie de n'importe quel nœud
- e.g. une article, une produit, une formulaire
- Bref, si un nœud est referencable, il est refenceable par tout
- Parce que il est attribué une identifiant universel unique
Node Types
- Node Type <=> Schema (moins ou plus)
- Node Types sont héritable
- Chaque nœud a un type primaire
- Ils héritent tous de le type nt:base par exemple
Node Types
- Déclarer qu'une propriété est recquis
- Déclarer qu'un certain enfant est recquis
- Spécifier que une propertié doit être crée automatiquement
- Imposer le type d'une propertié
- Spécifier si une properté peut avoir plusieurs valeurs
- Elles sont analogues à la notion de Class en PHP
Node Types
Mixins
- Permet un genre d'héritage multiple
- Elles sont analogues à la notion de Trait en PHP
Node Types
Mixins
- nt:title
- nt:lastModified
- nt:created
- nt:versionable
Node Types
Mixins
- -- EXAMPLE WITH PHPCR-SHELL --
Node Types
- Sont typiquement définies avec les fichiers "CND"
Une notation pour le définition des types des nœuds
Quelques nœud types de défaut
nt:base
Le type du moins permissif
[nt:base]
- jcr:primaryType (NAME) autocreated mandatory protected COMPUTE
- jcr:mixinTypes (NAME) autocreated mandatory protected multiple COMPUTE
nt:unstructured
Le type le plus permissif
[nt:unstructured] > nt:base
orderable
- * (UNDEFINED)
- * (UNDEFINED) multiple
+ * = nt:unstructured multiple VERSION
nt:resource
Pour stocker les binaires avec le metadata ..
[nt:resource] > mix:referenceable
- jcr:encoding (STRING)
- jcr:mimeType (STRING) mandatory
- jcr:data (BINARY) mandatory primary
- jcr:lastModified (DATE) mandatory IGNORE
Implications ORM
- Node type = Class
- Mixin = Trait
- Hmm...
- Alors, le mapping est plus isomorphique que avec une RDBMS
- Mais, ça c'est une autre sujet!
Query
- PHPCR fournit une interface de query objet orientée
Query
$session = // we get the session
$workspace = $session->getWorkspace();
$queryManager = $workspace->getQueryManager();
$qom = $queryManager->getQOMFactory();
// START OF QUERY
$source = $qom->selector('s', '[nt:unstructured]');
$constraint = $qom->comparison(
$qom->nodeLocalName('s'),
QOMConstants::JCR_OPERATOR_NOT_EQUAL_TO,
$qom->literal('foobar')
);
$query = $qom->createQuery($source, $constraint, array(), array());
$queryResult = $query->execute();
Query
Heuresement il est possible aussi de faire les queries en mode string
// JCR-SQL2
$sql = "SELECT * FROM [nt:unstructured] AS s WHERE LOCALNAME('s') = 'foobar'";
$query = $queryManager->createQuery($sql, 'JCR-SQL2');
$queryResult = $query->execute();
Query
- Pas d'aggregation!
- Pas de UPDATE, INSERT, etc.
- Full text search!
- Possiblité de cherche le repositorié entière
Versioning
Versioning est activé pour une node avec le mixin "mix:versionable"
$node->addMixin('mix:versionable');
Versioning
// FIX ME!!
$vm = $session->getWorkspace()->getVersionManager();
$node = $session->getNode('/this/is/a/versionable/node');
$node->setProperty('title', 'Hello World!');
$session->save();
$vm->checkpoint($node->getPath();
$vm->setProperty('title', 'Foobar');
$version = $vm->checkin($node->getPath());
$previous = $version->getLinearPredecessor();
$frozenNode = $previous->getFrozenNode();
echo $previous->getProperty('title');
// OUTPUT: Hello World!
Import / Export
-
Exporter les nœuds d'un certain point dans la hiérarchie de nœud
-
Importer les nœuds d'un certain point dans la hiérarchie de nœud
- Tous est fait dans une format XML
- Facile de migrer de une implémentation repository à une autre
Import / Export
$stream = fopen('my_content.xml', 'w');
$session->exportDocumentView(
'/path/to/what/i/want',
$stream,
);
Import / Export
$session->importXml('/import/to/here', 'my_content.xml');
Autres choses
Access Control
- Savori si une utilisateur a permission de faire une certaine type d'operation sur une certaine node selon le session
- Possiblitie de creer et appliquer policies avec classes de type "AccessControlPolicyInterface" classes qui pourait contient logique au besoin
Autre choses
Locking et Transactions
Autre choses
Voir le spec :)
PHPCR-Shell
- Projet perso ..
- Vise à fournir une interface CLI complèt à les repositotrys PHPCR
- Edition avec votre editeur de shell préféré
- Inspiré par les shells de navigation *sh et RDBMS
- Traverse le heirachie et gerer les nodes avec les commandes du shell (cd, ls, mv, cp)
- Et faire les raquettes comme une shell RDBMS
- Le behavior de chaque commanda est précisé avec Behat
Welcome to the PHPCR shell (1.0-pre-alpha).
PHPCR > ls
+--------------+-----------------+-------+
| Node / Prop | Type | Value |
+--------------+-----------------+-------+
| / | rep:root | |
| propriétés/ | nt:unstructured | |
+--------------+-----------------+-------+
2 node(s)
PHPCR > select * from [nt:unstructured] where localname() = 'propriétés';
| Row: #0 Score: 2
| Sel: nt:unstructured Path: /propriétés UID: none
+-----------------+---------------+----------+--------------------------------------+
| Name | Type | Multiple | Value |
+-----------------+---------------+----------+--------------------------------------+
| uri | URI | no | thisisuri |
| double | Long | no | 10 |
| binary | Binary | no | (binary data) |
| long | Long | no | 1234 |
| reference | Reference | no | 13543fc6-1abf-4708-bfcc-e49511754b40 |
| date | Date | no | 2011-04-21T14:34:20+01:00 |
| multivalue | String | yes | [0] thisisstring |
| | | | [1] thisisstring |
| string | String | no | thisisstring |
| boolean | Boolean | no | true |
| jcr:primaryType | Name | no | nt:unstructured |
+-----------------+---------------+----------+--------------------------------------+
1 rows in set (0.23 sec)
PHPCR in the wild
Jackalope
Framework
- Collecte des Bundles Symfony qui fournit les fonctionnalités CMS
w:
Références et ressources
@dantleech