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 brings Doctrine-style object document mapping to PHP Content Repository (PHPCR) implementations. Map PHP objects to nodes and query content repositories via familiar Doctrine APIs. Supports Jackrabbit and Doctrine DBAL setups, with tests and docs available.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup in Laravel

  1. Install the Package:

    composer require doctrine/phpcr-odm jackalope/jackalope-doctrine-dbal
    

    (Use jackalope/jackalope-jackrabbit for Jackrabbit backend if needed.)

  2. Configure PHPCR Backend (e.g., Doctrine DBAL):

    // config/phpcr.php
    return [
        'connections' => [
            'default' => [
                'driver' => 'jackalope/doctrine-dbal',
                'db' => [
                    'driver' => 'pdo_mysql',
                    'host' => env('DB_HOST'),
                    'dbname' => env('DB_DATABASE'),
                    'user' => env('DB_USERNAME'),
                    'password' => env('DB_PASSWORD'),
                ],
                'repository_path' => '/',
            ],
        ],
    ];
    
  3. Create a Service Provider (app/Providers/PHPCRServiceProvider.php):

    use Doctrine\ODM\PHPCR\Configuration;
    use Doctrine\ODM\PHPCR\DocumentManager;
    use Doctrine\ODM\PHPCR\DocumentManagerFactory;
    
    class PHPCRServiceProvider extends ServiceProvider {
        public function register() {
            $config = new Configuration();
            $config->setMetadataDirectory(__DIR__.'/../resources/odm');
            $config->setProxyDir(__DIR__.'/../storage/framework/proxies');
            $config->setProxyNamespace('Proxies');
    
            $conn = $this->app['config']['phpcr.connections.default'];
            $config->setRepositoryImplementation($conn['driver']);
            $config->setRepositoryConfig($conn);
    
            $dmFactory = DocumentManagerFactory::create($config);
            $this->app->singleton(DocumentManager::class, function () use ($dmFactory) {
                return $dmFactory->createDocumentManager();
            });
        }
    }
    
  4. Define a Document Model (app/Models/Page.php):

    use Doctrine\ODM\PHPCR\Mapping\Annotations as PHPCR;
    
    #[PHPCR\Document]
    class Page {
        #[PHPCR\Id]
        private $id;
    
        #[PHPCR\String]
        private $title;
    
        #[PHPCR\ReferenceMany(targetDocument="Page")]
        private $children;
    
        public function __construct() {
            $this->children = new \Doctrine\Common\Collections\ArrayCollection();
        }
    }
    
  5. First Usage (e.g., in a controller):

    use Doctrine\ODM\PHPCR\DocumentManager;
    
    public function createPage(DocumentManager $dm) {
        $page = new Page();
        $page->setTitle('Home');
        $dm->persist($page);
        $dm->flush();
    }
    

Key First Use Case

Hierarchical Content Creation:

// Create a blog post with categories (parent-child relationship)
$blog = new Page();
$blog->setTitle('Blog');
$dm->persist($blog);

$post = new Page();
$post->setTitle('First Post');
$post->setParentDocument($blog); // Sets hierarchy
$dm->persist($post);

$dm->flush();

Implementation Patterns

1. Document Lifecycle Management

  • Persist/Flush:

    $dm->persist($document); // Marks as "new"
    $dm->flush(); // Saves to PHPCR
    
  • Merge (Deprecated in 2.0+): Use find() + manual updates instead of merge().

  • Detach:

    $dm->detach($document); // Removes from DocumentManager
    

2. Hierarchical Queries

  • Find by Path:

    $dm->find(null, '/site/blog/posts'); // Returns all posts under /site/blog/posts
    
  • Subtree Queries:

    $query = $dm->createQueryBuilder('Page')
        ->where('jcr:path LIKE /site/%')
        ->getQuery();
    
  • Parent-Child Relationships:

    $parent = $dm->find(Page::class, '/site/home');
    $children = $parent->getChildren(); // ChildrenCollection
    

3. Event Listeners (Lifecycle Hooks)

  • Pre-Persist:

    $dm->getEventManager()->addEventListener(
        'prePersist',
        function ($event) {
            $document = $event->getDocument();
            if ($document instanceof Page) {
                $document->setCreatedAt(new \DateTime());
            }
        }
    );
    
  • Post-Flush:

    $dm->getEventManager()->addEventListener(
        'postFlush',
        function () {
            // Log or cache after flush
        }
    );
    

4. Bulk Operations

  • Batch Persist:

    $pages = [];
    foreach ($rawData as $data) {
        $pages[] = new Page($data);
    }
    $dm->persistAll($pages);
    $dm->flush();
    
  • Delete Subtree:

    $dm->remove($parentDocument); // Deletes parent + all children
    $dm->flush();
    

5. Integration with Laravel

  • Service Container Binding:

    $this->app->bind('phpcr.dm', function () {
        return $this->app->make(DocumentManager::class);
    });
    
  • Eloquent Coexistence:

    // Hybrid repository example
    $user = User::find(1); // Eloquent
    $page = $dm->find(Page::class, '/home'); // PHPCR ODM
    
  • Caching:

    use Symfony\Contracts\Cache\CacheInterface;
    
    $cache = $this->app->make(CacheInterface::class);
    $dm->getConfiguration()->setMetadataCacheImpl($cache);
    

6. Custom ID Generators

  • UUID:

    #[PHPCR\Id(generator="uuid")]
    private $id;
    
  • Path-Based:

    #[PHPCR\Id(strategy="path")]
    private $id;
    

7. Field Types

Type Annotation Example Use Case
String @String Titles, descriptions
Binary @Binary File uploads
DateTime @DateTime Publish dates
ReferenceOne @ReferenceOne(targetDocument="Page") Parent-child links
ReferenceMany @ReferenceMany(targetDocument="Page") Children collections
Boolean @Boolean Published flag
Float @Float Ratings

Gotchas and Tips

1. Common Pitfalls

  • Path Collisions: Avoid manually setting jcr:path unless necessary. Let PHPCR generate paths automatically. Fix: Use @Id(strategy="path") with caution.

  • Circular References: Bidirectional @ReferenceOne/@ReferenceMany can cause infinite loops. Fix: Use lazy loading or @PHPCR\Lazy.

  • Transaction Isolation: PHPCR and Eloquent transactions may not auto-commit together. Fix: Wrap in explicit transactions:

    DB::transaction(function () use ($dm) {
        $dm->flush();
    });
    
  • Case Sensitivity: Node paths are case-sensitive in PHPCR. Fix: Normalize paths (e.g., /site/Blog vs /site/blog).

  • Large Subtrees: Querying deep hierarchies (e.g., /site/*/*/*) can be slow. Fix: Use jcr:level or limit depth:

    $qb->where('jcr:level < 5');
    

2. Debugging Tips

  • Enable PHPCR Logging:

    $dm->getConfiguration()->setSQLLogger(new \Doctrine\ODM\PHPCR\Logging\SQLLogger());
    
  • Check Node Existence:

    if (!$dm->find(null, '/nonexistent')) {
        throw new \RuntimeException('Node not found');
    }
    
  • Clear Metadata Cache:

    php artisan cache:clear
    

    (If using Symfony Cache.)

3. Configuration Quirks

  • PSR-6 Cache Requirement: Ensure your cache driver implements Psr\Cache\CacheInterface. Fix: Use symfony/cache or predis/predis:

    $cache = new \Symfony\Contracts\Cache\ArrayCache();
    $config->setMetadataCacheImpl($cache);
    
  • Jackrabbit Java Dependency: If using Jackrabbit, ensure:

    • Java 8+ is installed.
    • Port 9090 is free (default Jackrabbit port).
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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope