Need a solution that can scale both from small to large projects and we rather not reinvent the wheel!
PHPCR provides a standardized API that can be used by any PHP content management system to interface with any content repository.
* Not yet implemented in Jackalope-Jackrabbit
<jcr:root> <cms> <pages> <home title="Hello"> <block title="News" content="Today: PHPCR presentation"/> </home> <contact title="Contact" content="phpcr-users@groups.google.com"/> </pages> </cms> </jcr:root>
Source: phpcr.github.com
use PHPCR\SimpleCredentials; // start of implementation specific configuration // use Jackalope\RepositoryFactoryJackrabbit as Factory; $parameters = array( 'jackalope.jackrabbit_uri' => 'http://localhost:8080/server', ); $repository = Factory::getRepository($parameters); // end of implementation specific configuration // $creds = new SimpleCredentials('admin','admin'); $session = $repository->login($creds, 'default');
$root = $session->getRootNode(); // Nodes must be added as child of another node $node = $root->addNode('test', 'nt:unstructured'); // New node is immediately available to this session $node = $session->getNode('/test'); // Create/update a property $node->setProperty('prop', 'value'); // New node is now available for all sessions $session->save(); // Delete the node and all its children $node->remove(); // Fails if a concurrent session also changed '/test' $session->save();
$node = $session->getNode('/site/content'); foreach ($node->getNodes() as $child) { var_dump($child->getName()); } // or in short foreach ($node as $child) { var_dump($child->getName()); } // filter on node names foreach ($node->getNodes('di*') as $child) { var_dump($child->getName()); }
// make versionable $node = $session->getNode('/site/content/about'); $node->addMixin('mix:versionable'); $session->save(); // create initial version $node->setProperty('title', 'About'); $session->save(); // check-in (create version) // and check-out (prepare for further updates) // persisted immediately without a save() call $vm = $session->getWorkspace()->getVersionManager(); $vm->checkpoint($node->getPath());
// update node with some changes $node->setProperty('title', 'Ups'); $session->save(); // create another version, leave in read only state $vm->checkin($node->getPath()); $base = $vm->getBaseVersion($node->getPath()); $current = $base->getLinearPredecessor(); $previous = $current->getLinearPredecessor(); // get snapshot of old version to look around $frozenNode = $previous->getFrozenNode(); echo $frozenNode->getProperty('title'); // About // set the live data back to what is in this version $vm->restore(true, $previous); $node = $session->getNode('/site/content/about'); echo $node->getProperty('title'); // About
$qm = $workspace->getQueryManager(); // unlike SQL, in SQL2 "*" does not return all // columns but at least the path and match score $sql = "SELECT * FROM [nt:unstructured] WHERE [nt:unstructured].type = 'nav' AND ISDESCENDANTNODE('/some/path') ORDER BY score, [nt:unstructured].title"; $query = $qm->createQuery($sql, 'JCR-SQL2'); $query->setLimit($limit); $query->setOffset($offset); $queryResult = $query->execute(); foreach ($queryResult->getNodes() as $node) { var_dump($node->getPath()); }
(With phpcr-utils)
$qm = $workspace->getQueryManager(); $factory = $qm->getQOMFactory(); // SELECT * FROM nt:unstructured // WHERE name NOT IS NULL // LIMIT 10 OFFSET 10 $qb = new QueryBuilder($factory); $qb->select($factory->selector('nt:unstructured')) ->where($factory->propertyExistence('name')) ->setFirstResult(10) ->setMaxResults(10) ->execute();
$test = $session->getNode('/test'); $test1 = $session1->getNode('/test'); $test->remove(); $test1->setProperty('prop', 'value'); $session->save(); // this will fail as the node is gone $session1->save();
// prepare $test = $session->getNode('/test'); $test->addMixin('mix:lockable'); $session->save(); // use $lm = $session->getWorkspace()->getLockManager(); // lock node and children for 5 seconds $lock = $lm->lock('/test', true, true, 5); $test1 = $session1->getNode('/test'); // here you will get an exception that node is locked $test1->setProperty('prop', 'value');
A test suite for PHPCR makes sure all implementations interpret the specification the same way.
Test results using Jackalope with the Jackrabbit backend.
......................................S.........S.....II..... 61 / 1222 ( 4%) ...........S.S............................................... 122 / 1222 ( 9%) ...........SS.......SS.S.......S............................. 183 / 1222 ( 14%) ............................................................. 244 / 1222 ( 19%) ............................................................. 305 / 1222 ( 24%) ............................................................. 366 / 1222 ( 29%) ............................................................. 427 / 1222 ( 34%) ..............................S.........SSS..............I.I. 488 / 1222 ( 39%) I.I.........................I...................I..I........S 549 / 1222 ( 44%) I............................................................ 610 / 1222 ( 49%) .....S.......I.....................S..S...................... 671 / 1222 ( 54%) .................SS...............SSSS..S.................... 732 / 1222 ( 59%) .......................................................SSSSS. 793 / 1222 ( 64%) ..........................S.............I......S...........I. 854 / 1222 ( 69%) .............................SS..................S........... 915 / 1222 ( 74%) ............................................................. 976 / 1222 ( 79%) ............................................................. 1037 / 1222 ( 84%) ...............................S............................. 1098 / 1222 ( 89%) ...........SSSS...........SSS................................ 1159 / 1222 ( 94%) ........................................SSSSSS............... 1220 / 1222 ( 99%) . Time: 03:23, Memory: 93.50Mb OK, but incomplete or skipped tests! Tests: 1212, Assertions: 6797, Incomplete: 17, Skipped: 49.
namespace Foo; use Doctrine\ODM\PHPCR\Mapping as PHPCRODM; /** @PHPCRODM\Document */ class Bar { /** @PHPCRODM\Id */ public $id; /** * @PHPCRODM\ParentDocument */ public $parent; /** @PHPCRODM\Nodename */ public $nodename; /** @PHPCRODM\String */ public $text; }
// Create $document = new Foo\Bar(); $document->parent = $dm->find(null, '/'); $document->nodename = 'test'; $document->text = 'Test text'; $dm->persist($document); $dm->flush(); // Read $document = $dm->find(null, '/test'); // Update $document->text = 'foo!'; $dm->flush(); // Remove $dm->remove($document); $dm->flush();
/** * Map the child node named the-logo * @PHPCR\Child(name="the-logo") */ public $logo; /** * All child nodes starting with "a". * @PHPCR\Children(filter="a*") */ public $children; /** @PHPCR\ReferenceOne */ public $reference; /** @PHPCR\Referrers */ public $referrers;
doctrine_phpcr: # configure the PHPCR session session: backend: type: doctrinedbal connection: doctrine.dbal.default_connection workspace: default # enable the ODM layer odm: auto_mapping: true auto_generate_proxy_classes: %kernel.debug% locales: en: - en - fr fr: - fr - en
|
|
Please give me feedback:
@dbu on Twitter, or just david@liip.ch