Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Phpcr Odm Laravel Package

doctrine/phpcr-odm

Doctrine PHPCR-ODM maps PHP objects to a PHPCR content repository (e.g., Jackrabbit or DBAL-backed implementations). Provides persistence, querying, and schema mapping via Doctrine-style metadata, with tooling, docs, and test setups for multiple backends.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Package:

    composer require doctrine/phpcr-odm
    

    Choose a PHPCR implementation (e.g., Jackrabbit or Doctrine DBAL):

    composer require jackalope/jackalope-jackrabbit  # or jackalope/jackalope-doctrine-dbal
    
  2. Configure the ODM: Create a config/packages/doctrine_phpcr_odm.yaml (Symfony) or config/odm.php (Laravel):

    doctrine_phpcr_odm:
        connections:
            default:
                url: 'http://localhost:8080/server'  # Jackrabbit example
                # OR for DBAL:
                # url: 'mysql://user:pass@localhost/db'
                manager_type: 'document'
                backend_options:
                    # PHPCR-specific config (e.g., Jackrabbit workspace)
    
  3. Define a Document: Use PHP attributes (recommended) or XML/YAML:

    use Doctrine\ODM\PHPCR\Mapping\Annotations as PHPCR;
    
    #[PHPCR\Document]
    class Article {
        #[PHPCR\Id]
        private string $id;
    
        #[PHPCR\String]
        private string $title;
    
        #[PHPCR\ReferenceOne(targetDocument: Article::class)]
        private ?Article $parent = null;
    
        #[PHPCR\Children]
        private Collection $children;
    }
    
  4. First Query:

    $dm = $container->get('doctrine_phpcr.odm.default_document_manager');
    $articles = $dm->createQueryBuilder('Article')
        ->where('title LIKE :title')
        ->setParameter('title', '%Laravel%')
        ->getQuery()
        ->execute();
    

Implementation Patterns

Core Workflows

  1. CRUD with Hierarchy:

    // Create a nested document
    $parent = $dm->find(Article::class, '/articles/parent');
    $child = new Article();
    $child->setTitle('Child Article');
    $parent->addChild($child);
    $dm->persist($child);
    $dm->flush();
    
    // Traverse hierarchy
    foreach ($parent->getChildren() as $child) {
        echo $child->getTitle();
    }
    
  2. Querying Hierarchies:

    // Path-based query
    $qb = $dm->createQueryBuilder('Article')
        ->where('jcr:path LIKE /articles/%')
        ->getQuery();
    
    // Ancestor/descendant queries
    $qb = $dm->createQueryBuilder('Article')
        ->where('jcr:ancestor-node(/articles/parent)')
        ->getQuery();
    
  3. Lifecycle Events:

    // Pre-persist hook
    $dm->getEventManager()->addEventListener(
        'prePersist',
        function (LifecycleEventArgs $args) {
            $doc = $args->getObject();
            if ($doc instanceof Article) {
                $doc->setCreatedAt(new \DateTime());
            }
        }
    );
    
  4. Bulk Operations:

    // Batch updates
    $dm->createQueryBuilder('Article')
        ->update()
        ->set('title', 'Updated Title')
        ->where('jcr:path LIKE /articles/%')
        ->getQuery()
        ->execute();
    

Integration Tips

  • Symfony: Use doctrine_phpcr_odm bundle for autoconfiguration.
  • Laravel: Bind the DocumentManager to the container and use phpcr-odm facade:
    $this->app->bind('phpcr-odm', function ($app) {
        return $app->make('doctrine_phpcr.odm.default_document_manager');
    });
    
  • Migrations: Use doctrine/phpcr-migrations for schema changes:
    composer require doctrine/phpcr-migrations
    php bin/console doctrine:phpcr:migrations:diff
    

Gotchas and Tips

Common Pitfalls

  1. Session Management:

    • PHPCR sessions are not automatically flushed if no ODM changes exist. Call $dm->flush() explicitly for session commits.
    • Fix: Always flush after bulk operations or hierarchical updates.
  2. Path Conflicts:

    • Manual path assignments (e.g., $doc->setPath('/custom/path')) can break hierarchy integrity.
    • Tip: Use ReferenceOne/Children for parent-child relationships instead of raw paths.
  3. Query Limitations:

    • PHPCR lacks SQL-like JOIN syntax. Use jcr:path or jcr:ancestor-node() for hierarchical queries.
    • Workaround: Pre-fetch related documents with ->fetch('children').
  4. Attribute Migration:

    • BC Break: Annotations (e.g., @PHPCR\Field) are deprecated. Use #[PHPCR\Field] instead.
    • Fix: Run php bin/console make:odm-migration to update mappings.
  5. Transaction Isolation:

    • PHPCR transactions do not roll back on PHP exceptions by default. Wrap critical sections:
    $dm->beginTransaction();
    try {
        $dm->persist($doc);
        $dm->flush();
        $dm->commit();
    } catch (\Exception $e) {
        $dm->rollback();
        throw $e;
    }
    

Debugging Tips

  • Enable PHPCR Logging:
    # config/packages/monolog.yaml
    monolog:
        handlers:
            phpcr:
                type: stream
                path: "%kernel.logs_dir%/phpcr.log"
                level: debug
    
  • Check Session State:
    $dm->getSession()->save();
    $dm->getSession()->refresh();
    
  • Validate Paths: Use $dm->getPath($doc) to debug node locations during traversal.

Extension Points

  1. Custom ID Generators:

    #[PHPCR\Id(generator: 'uuid')]
    private string $id;
    

    Register a custom generator via Configuration::addCustomIdGenerator().

  2. Event Subscribers:

    $dm->getEventManager()->addEventSubscriber(
        new class implements EventSubscriber {
            public function getSubscribedEvents() {
                return ['prePersist', 'postRemove'];
            }
            // ...
        }
    );
    
  3. Query DSL Extensions: Extend Doctrine\ODM\PHPCR\Query\Expression\Comparison for custom predicates:

    class CustomComparison extends Comparison {
        public function __construct($field, $operator, $value) {
            parent::__construct($field, $operator, $value);
        }
        public function compile(Compiler $compiler) {
            $compiler->expr('custom_predicate(' . $this->field . ', ' . $this->value . ')');
        }
    }
    
  4. Backend-Specific Tweaks:

    • Jackrabbit: Configure workspace names in backend_options.
    • DBAL: Optimize jcr:path indexing for large trees.

Performance Quirks

  • Avoid Deep Traversals: PHPCR queries on deep hierarchies can be slow. Use jcr:level() or jcr:depth() limits.
  • Batch Loading: Fetch children in batches:
    $children = $parent->getChildren()->matching($dm->createQueryBuilder('Article')->getQuery());
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport