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 an object-relational mapper for PHP 8.1+ providing transparent persistence for PHP objects on top of Doctrine DBAL. Includes Doctrine Query Language (DQL), an object-oriented SQL-like dialect for flexible querying without duplication.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup in Laravel

  1. Installation:

    composer require doctrine/orm
    

    For Laravel-specific integration, use doctrine/dbal (dependency) and doctrine/doctrine-bundle (if using Symfony components).

  2. Configuration:

    • Define your entities (e.g., app/Models/User.php) with Doctrine annotations or XML/YAML mappings.
    • Example entity:
      use Doctrine\ORM\Mapping as ORM;
      
      #[ORM\Entity]
      class User {
          #[ORM\Id, ORM\GeneratedValue, ORM\Column]
          private ?int $id = null;
      
          #[ORM\Column(length: 255)]
          private string $name;
      }
      
  3. First Use Case:

    • Bootstrapping the ORM in Laravel:
      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);
      
      // Persist an entity
      $user = new User();
      $user->name = 'John Doe';
      $entityManager->persist($user);
      $entityManager->flush();
      

Implementation Patterns

Core Workflows

  1. CRUD Operations:

    • Create: Use persist() + flush().
    • Read: Query with EntityManager::find() or DQL:
      $users = $entityManager->createQuery('SELECT u FROM User u WHERE u.name = :name')
          ->setParameter('name', 'John Doe')
          ->getResult();
      
    • Update: Modify entity properties, then flush().
    • Delete: Use remove() + flush().
  2. Relationships:

    • Define with annotations (e.g., @OneToMany, @ManyToMany).
    • Fetch related entities with join in DQL or fetch="EAGER":
      #[ORM\OneToMany(targetEntity: Post::class, mappedBy: "author")]
      private Collection $posts;
      
  3. Repositories:

    • Extend Doctrine\ORM\EntityRepository for custom logic:
      namespace App\Repositories;
      
      use Doctrine\ORM\EntityRepository;
      
      class UserRepository extends EntityRepository {
          public function findActiveUsers() {
              return $this->createQueryBuilder('u')
                  ->where('u.isActive = :active')
                  ->setParameter('active', true)
                  ->getQuery()
                  ->getResult();
          }
      }
      
  4. Transactions:

    • Wrap operations in a transaction:
      $entityManager->beginTransaction();
      try {
          $entityManager->persist($user);
          $entityManager->flush();
          $entityManager->commit();
      } catch (\Exception $e) {
          $entityManager->rollback();
          throw $e;
      }
      

Integration with Laravel

  • Service Providers: Bind EntityManager in a Laravel service provider:

    public function register() {
        $this->app->singleton(EntityManager::class, function ($app) {
            $paths = [__DIR__.'/../app/Models'];
            $config = Setup::createAnnotationMetadataConfiguration($paths, true);
            $conn = $app['config']['database.connections.mysql'];
            return EntityManager::create($conn, $config);
        });
    }
    
  • Eloquent Interop: Use Doctrine alongside Eloquent by sharing the same DB connection or via a facade:

    use Doctrine\ORM\EntityManagerInterface;
    
    class UserService {
        public function __construct(private EntityManagerInterface $em) {}
    
        public function syncUser(User $user) {
            $this->em->persist($user);
            $this->em->flush();
            // Use Eloquent for other operations if needed
        }
    }
    

Gotchas and Tips

Common Pitfalls

  1. Lazy Loading:

    • Accessing uninitialized relationships triggers ProxyException. Use fetch="EAGER" or initialize with ->getPosts()->toArray().
    • Fix: Explicitly load relationships with ->getPosts() or use join fetch in DQL.
  2. Caching Metadata:

    • Doctrine caches metadata aggressively. Clear cache after schema updates:
      php vendor/bin/doctrine orm:clear-cache:metadata
      
  3. Connection Management:

    • Ensure the Doctrine connection matches Laravel’s DB config. Use doctrine/dbal adapters if needed.
  4. Case Sensitivity:

    • DQL is case-insensitive by default, but column names in annotations must match the DB schema exactly.
  5. Transaction Isolation:

    • Long-running transactions can lock tables. Use READ UNCOMMITTED or optimize queries.

Debugging Tips

  • SQL Logging: Enable SQL logging in config:

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

    Or use a file logger:

    $config->setSQLLogger(new \Doctrine\ORM\Logging\FileLogger('/tmp/doctrine.log'));
    
  • Query Profiling: Use the profiler to analyze slow queries:

    $query = $entityManager->createQuery('...');
    $query->useResultCache(true);
    $query->useQueryCache(true);
    

Extension Points

  1. Custom DQL Functions:

    • Register custom functions in the config:
      $config->addCustomStringFunction('CONCAT_WS', 'DoctrineExtensions\Query\Mysql\ConcatWs');
      
  2. Event Listeners:

    • Hook into lifecycle events (e.g., prePersist, postUpdate):
      $eventManager = $entityManager->getEventManager();
      $eventManager->addEventListener(
          \Doctrine\ORM\Events::prePersist,
          new \App\EventListeners\UserListener()
      );
      
  3. Second-Level Cache:

    • Enable for read-heavy apps:
      $config->setSecondLevelCacheEnabled(true);
      $config->setSecondLevelCache(new \Doctrine\Common\Cache\ApcuCache());
      
  4. Native Query Support:

    • Use createNativeQuery() for complex SQL:
      $query = $entityManager->createNativeQuery('SELECT * FROM users WHERE id = ?');
      $query->setParameter(1, 1);
      $result = $query->getResult();
      

Laravel-Specific Quirks

  • Migration Conflicts: Avoid mixing Doctrine schema updates with Laravel migrations. Use one tool per project.

  • Service Container Conflicts: If using both Doctrine and Eloquent, ensure no binding collisions (e.g., DBAL\Connection vs. Illuminate\Database\Connection).

  • Testing: Reset the entity manager between tests:

    $entityManager->getConnection()->beginTransaction();
    $entityManager->getConnection()->rollBack();
    
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