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

Persistence Laravel Package

doctrine/persistence

Doctrine Persistence provides shared abstractions for persistence and object mappers in the Doctrine ecosystem. It defines common interfaces and utilities used by Doctrine ORM and related libraries to manage mapping, metadata, and repository behavior across storage backends.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup in Laravel

To leverage doctrine/persistence in a Laravel project, start by installing the package via Composer:

composer require doctrine/persistence

First Use Case: Basic Object Persistence

The package provides core abstractions for object persistence. For a Laravel developer, this is most useful when integrating Doctrine ORM/ODM or building custom persistence layers. Here’s how to initialize a basic EntityManager:

use Doctrine\Persistence\ManagerRegistry;
use Doctrine\Persistence\ObjectManager;

// In a Laravel service provider or bootstrap file
$registry = new ManagerRegistry();
$entityManager = $registry->getManager(); // Assumes a configured manager

Key Classes to Explore

  1. ObjectManager: Core interface for persisting entities.
  2. EntityManager: Concrete implementation for ORM.
  3. ClassMetadata: Metadata about entity classes.
  4. MappingDriver: Loads metadata from annotations, XML, YAML, or attributes.

Where to Look First


Implementation Patterns

1. Integration with Laravel’s Service Container

Leverage Laravel’s IoC container to bind Doctrine’s ManagerRegistry and ObjectManager:

// In AppServiceProvider::boot()
$this->app->bind(ManagerRegistry::class, function ($app) {
    return new ManagerRegistry([
        'default' => $app->make(EntityManager::class), // Your configured EM
    ]);
});

2. Custom Metadata Workflows

Use ClassMetadataFactory to dynamically generate metadata for entities:

use Doctrine\Persistence\Mapping\ClassMetadataFactory;
use Doctrine\Persistence\Mapping\Driver\AnnotationDriver;

$driver = new AnnotationDriver(new ClassLocator());
$factory = new ClassMetadataFactory();
$factory->setMetadataDriver($driver, 'App\\Entities');

$metadata = $factory->getMetadataFor('App\\Entities\\User');

3. Repository Pattern

Implement custom repositories by extending Doctrine\Persistence\ObjectRepository:

use Doctrine\Persistence\ObjectRepository;

class UserRepository extends ObjectRepository
{
    public function findActiveUsers(): array
    {
        return $this->findBy(['isActive' => true]);
    }
}

4. Event Listeners and Subscribers

Attach listeners to ObjectManager events (e.g., prePersist, postUpdate):

use Doctrine\Persistence\Event\LifecycleEventArgs;

$em->getEventManager()->addEventListener(
    'prePersist',
    function (LifecycleEventArgs $args) {
        $entity = $args->getObject();
        $entity->setUpdatedAt(new DateTime());
    }
);

5. Dynamic Entity Hydration

Use ClassMetadata to inspect or modify entity fields at runtime:

$metadata = $em->getClassMetadata(User::class);
$metadata->mapField([
    'fieldName' => 'custom_field',
    'type' => 'string',
]);

6. Proxy Support

Leverage Doctrine’s proxy system for lazy-loading:

// Enable proxies in your EntityManager configuration
$config = new \Doctrine\ORM\Configuration();
$config->setProxyDir(__DIR__.'/proxies');
$config->setProxyNamespace('App\\Proxies');
$em = EntityManager::create($connection, $config);

Gotchas and Tips

1. PHP 8.1+ Requirement

  • Gotcha: Doctrine Persistence requires PHP 8.1+. Older versions will fail.
  • Tip: Use php -v to verify compatibility before integrating.

2. Deprecated Methods

  • Gotcha: Methods like ClassMetadataFactory::setMetadataFor() are deprecated (since 4.1+). Replace with ClassMetadataFactory::setMetadataForName() or avoid direct usage.
  • Tip: Use ClassMetadataFactory::getMetadataFor() for dynamic metadata loading.

3. ClassLocator for Attributes

  • Gotcha: If using attribute-based mapping (Doctrine ORM 2.8+), ensure ClassLocator is configured:
    $driver = new AttributeDriver(new ClassLocator());
    
  • Tip: For Laravel, autowire ClassLocator via Doctrine\Persistence\Mapping\Driver\ClassLocator.

4. Proxy Namespace Conflicts

  • Gotcha: Proxy classes may conflict with existing classes if namespaces collide.
  • Tip: Customize the proxy namespace in EntityManager configuration:
    $config->setProxyNamespace('App\\Generated\\Proxies');
    

5. Enum Support

  • Gotcha: Pre-4.1 versions had limited enum support. Newer versions (4.1+) include fixes.
  • Tip: Use getFieldValue()/setFieldValue() for dynamic enum handling:
    $metadata->setFieldValue($entity, 'status', UserStatus::ACTIVE);
    

6. Debugging Metadata Issues

  • Gotcha: Metadata loading failures (e.g., missing annotations) can silently break persistence.
  • Tip: Enable debug mode in EntityManager:
    $em->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger());
    $em->getConfiguration()->setMetadataCacheImpl(null); // Disable cache for debugging
    

7. Laravel-Specific Quirks

  • Gotcha: Laravel’s autoloader may not recognize Doctrine’s proxy classes.
  • Tip: Register proxy paths in composer.json:
    "autoload": {
        "psr-4": {
            "App\\Proxies\\": "storage/proxies/"
        }
    }
    

8. Performance with Large Datasets

  • Gotcha: Eager-loading metadata for all entities upfront can be slow.
  • Tip: Use ClassMetadataFactory::getMetadataForName() sparingly and cache results:
    $cache = new \Doctrine\Common\Cache\FilesystemCache(__DIR__.'/cache');
    $factory->setMetadataCacheImpl($cache);
    

9. Testing with Doctrine Persistence

  • Tip: Use Doctrine\Persistence\ObjectManager interfaces in tests to avoid ORM dependencies:
    $this->mockObjectManager = $this->createMock(ObjectManager::class);
    $this->mockObjectManager->method('find')->willReturn(new User());
    

10. Extending ObjectManager

  • Tip: Decorate ObjectManager for custom logic:
    use Doctrine\Persistence\ObjectManager;
    
    class CustomObjectManager implements ObjectManager
    {
        private $decorated;
    
        public function __construct(ObjectManager $decorated)
        {
            $this->decorated = $decorated;
        }
    
        public function find($id, $lockMode = null, $lockVersion = null)
        {
            $entity = $this->decorated->find($id, $lockMode, $lockVersion);
            // Add custom logic here
            return $entity;
        }
    
        // Delegate all other methods to $this->decorated
    }
    
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.
codraw/framework-extra-bundle
codraw/messenger
codraw/security
codraw/mailer
codraw/contracts
codraw/profiling
codraw/dependency-injection
codraw/tester
codraw/core
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony