PHPCR – PHP Content Repository - Une Introduction – Et c'est quoi un Content Repository?



PHPCR – PHP Content Repository - Une Introduction – Et c'est quoi un Content Repository?

0 0


phpcr-presentation

PHPCR Presentation using reveal.js

On Github dantleech / phpcr-presentation

PHPCR

PHP Content Repository - Une Introduction

Par Daniel Leech / @dantleech

Qu'est-ce que c'est PHPCR?

C'est:

  • PHP
  • Content
  • Repository

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

JCR!

Le specification

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

Comment ça fonctionne?

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!

The Repository Model

Quelques aspets de PHPCR

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

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"

CND - Compact Node Type Definition

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

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

Observation

  • Events

Autre choses

Locking et Transactions

Autre choses

Voir le spec :)

Outils

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

ORM

Doctrine PHPCR-ODM

  • ORM for PHPCR

Framework

  • Collecte des Bundles Symfony qui fournit les fonctionnalités CMS

CMS

Websites

w:

Societes

Questions?

Références et ressources

@dantleech