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

Orm Laravel Package

doctrine/orm

Doctrine ORM is a PHP 8.1+ object-relational mapper that provides transparent persistence for objects on top of Doctrine DBAL. Includes DQL, an object-oriented SQL-like query language inspired by Hibernate HQL, for flexible, powerful querying.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup in Laravel

  1. Installation:

    composer require doctrine/orm
    

    For Laravel integration, use doctrine/dbal (dependency) and optionally doctrine/doctrine-bundle (Symfony-based projects).

  2. First Use Case: Define an entity (model) and map it to a database table:

    // app/Models/User.php
    use Doctrine\ORM\Mapping as ORM;
    
    #[ORM\Entity(repositoryClass: UserRepository::class)]
    #[ORM\Table(name: 'users')]
    class User
    {
        #[ORM\Id, ORM\GeneratedValue, ORM\Column(type: 'integer')]
        private ?int $id = null;
    
        #[ORM\Column(type: 'string', length: 255)]
        private string $name;
    
        // Getters/setters...
    }
    
  3. Bootstrap ORM: In bootstrap/app.php or a service provider:

    use Doctrine\ORM\Tools\Setup;
    use Doctrine\ORM\EntityManager;
    
    $paths = [__DIR__.'/app/Models'];
    $isDevMode = true;
    $config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode);
    $conn = ['driver' => 'pdo_mysql', 'user' => 'user', 'password' => 'pass', 'dbname' => 'db'];
    $entityManager = EntityManager::create($conn, $config);
    
  4. First Query:

    $user = $entityManager->find(User::class, 1);
    $users = $entityManager->createQuery('SELECT u FROM App\Models\User u')->getResult();
    

Key First Steps

  • Schema Generation: Use Doctrine\ORM\Tools\SchemaTool to generate/update DB schema.
  • DQL: Write queries in Doctrine Query Language (DQL) instead of raw SQL.
  • Repositories: Extend Doctrine\ORM\EntityRepository for custom logic.

Implementation Patterns

Core Workflows

  1. CRUD Operations:

    // Create
    $user = new User();
    $user->setName('John Doe');
    $entityManager->persist($user);
    $entityManager->flush();
    
    // Update
    $user->setName('Jane Doe');
    $entityManager->flush();
    
    // Delete
    $entityManager->remove($user);
    $entityManager->flush();
    
  2. Querying with DQL:

    // Basic query
    $query = $entityManager->createQuery('SELECT u FROM App\Models\User u WHERE u.name = :name')
        ->setParameter('name', 'John Doe');
    $users = $query->getResult();
    
    // Joins
    $query = $entityManager->createQuery(
        'SELECT u, p FROM App\Models\User u JOIN u.posts p WHERE p.title LIKE :title'
    )->setParameter('title', '%Doctrine%');
    
  3. Relationships:

    #[ORM\OneToMany(mappedBy: 'user', targetEntity: Post::class)]
    private Collection $posts;
    
    // Fetch related entities
    $user = $entityManager->find(User::class, 1);
    foreach ($user->getPosts() as $post) { ... }
    
  4. Transactions:

    $entityManager->beginTransaction();
    try {
        $entityManager->persist($user);
        $entityManager->flush();
        $entityManager->commit();
    } catch (\Exception $e) {
        $entityManager->rollback();
        throw $e;
    }
    

Integration Tips

  • Laravel Eloquent Hybrid: Use laravel-doctrine/orm bridge for seamless Eloquent + Doctrine integration.
  • Caching: Enable second-level cache for queries:
    $config->setSecondLevelCacheEnabled(true);
    $config->setSecondLevelCache(new \Doctrine\Common\Cache\ApcuCache());
    
  • Events: Listen to lifecycle events:
    #[ORM\PrePersist]
    public function prePersist() {
        $this->createdAt = new \DateTime();
    }
    
  • Custom Repositories: Extend EntityRepository for complex logic:
    class UserRepository extends EntityRepository {
        public function findActiveUsers() {
            return $this->createQueryBuilder('u')
                ->where('u.isActive = :active')
                ->setParameter('active', true)
                ->getQuery()
                ->getResult();
        }
    }
    

Gotchas and Tips

Common Pitfalls

  1. Lazy Loading:

    • Issue: Accessing uninitialized relationships triggers ProxyQueryException.
    • Fix: Use ->initialize() or ->get() with DISTINCT to eager-load:
      $user = $entityManager->find(User::class, 1);
      $user->getPosts()->initialize(); // Force load
      
    • Better: Always eager-load in queries:
      $query->leftJoin('u.posts', 'p')->addSelect('p');
      
  2. N+1 Problem:

    • Issue: Iterating over collections triggers N+1 queries.
    • Fix: Use ->fetch('EXECUTE') or ->getArrayResult() for bulk operations:
      $query->setFetchMode('App\Models\User', 'array');
      
  3. Case Sensitivity:

    • Issue: DQL is case-insensitive by default (unlike SQL).
    • Fix: Use LOWER() or UPPER() for case-sensitive queries:
      $query->where('LOWER(u.name) = LOWER(:name)');
      
  4. Transaction Management:

    • Issue: Forgetting to commit/rollback transactions.
    • Fix: Use try-catch blocks or wrap in a service with transaction handling.
  5. Entity Manager Lifecycle:

    • Issue: Using the same EntityManager across requests (thread-safety).
    • Fix: Create a new EntityManager per request (Laravel service container handles this).

Debugging Tips

  1. SQL Logging:

    $config->setSQLLogger(new \Doctrine\ORM\Logging\EchoSQLLogger());
    

    Or use Doctrine\ORM\Logging\DebugStack for detailed logging.

  2. Query Profiling:

    $profiler = new \Doctrine\ORM\Tools\Console\Helper\ProfilerHelper($entityManager);
    $profiler->collect();
    
  3. Schema Validation:

    php vendor/bin/doctrine orm:validate-schema
    

Extension Points

  1. Custom Types:

    #[ORM\Column(type: 'json')]
    private array $metadata;
    
    // Or create a custom type:
    class JsonType extends \Doctrine\DBAL\Types\JsonType { ... }
    
  2. Event Subscribers:

    use Doctrine\Common\EventSubscriber;
    
    class MySubscriber implements EventSubscriber {
        public function getSubscribedEvents() {
            return ['prePersist', 'postUpdate'];
        }
    
        public function prePersist(LifecycleEventArgs $args) { ... }
    }
    
  3. Filters:

    #[ORM\Table(name: 'users', options: ['indexes' => ['active_idx' => 'is_active']])]
    #[ORM\Entity(repositoryClass: UserRepository::class)]
    class User {
        #[ORM\Column(name: 'is_active', type: 'boolean')]
        private bool $isActive;
    }
    
    // In repository:
    $filter = new \Doctrine\ORM\Mapping\ClassMetadata($entityManager->getClassMetadata(User::class));
    $filter->addFilter('active', 'isActive = :active');
    
  4. Hydration:

    // Return scalar arrays
    $query->setHydrationMode(\Doctrine\ORM\Query::HYDRATE_ARRAY);
    
    // Return objects with custom constructor
    $query->setHydrationMode(\Doctrine\ORM\Query::HYDRATE_CUSTOM, 'App\Hydrator\MyHydrator');
    

Laravel-Specific Quirks

  1. Service Container Binding: Bind EntityManager in a service provider:

    $this->app->singleton(EntityManager::class, function ($app) {
        $config = Setup::createAnnotationMetadataConfiguration([...]);
        return EntityManager::create($app['db']->connection()->getPdo(), $config);
    });
    
  2. Migrations: Use doctrine/dbal migrations alongside Laravel migrations:

    php vendor/bin/doctrine orm:schema-tool:create
    
  3. Caching: Disable Doctrine cache in production if using Laravel’s cache:

    $config->setMetadataCacheImpl(null);
    $config->setQueryCacheImpl(null);
    
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