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

laravel-doctrine/orm

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require laravel-doctrine/orm
    php artisan vendor:publish --tag="config" --provider="LaravelDoctrine\ORM\DoctrineServiceProvider"
    
    • Review config/doctrine.php for database connection settings (e.g., dbal.connection, orm.connection).
  2. Define a Doctrine Entity:

    // app/Models/User.php
    use Doctrine\ORM\Mapping as ORM;
    
    #[ORM\Entity(repositoryClass: "App\Repositories\UserRepository")]
    class User
    {
        #[ORM\Id, ORM\GeneratedValue, ORM\Column(type: "integer")]
        private ?int $id = null;
    
        #[ORM\Column(type: "string", length: 180, unique: true)]
        private string $email;
    
        // Getters/setters...
    }
    
  3. First Query:

    use LaravelDoctrine\ORM\Facades\EntityManager;
    
    $user = EntityManager::getRepository(User::class)->find(1);
    

First Use Case: Migrating from Eloquent

Replace Eloquent models with Doctrine entities and use EntityManager facade for CRUD operations. Example:

// Create
$user = new User();
$user->setEmail('test@example.com');
EntityManager::persist($user);
EntityManager::flush();

// Query
$users = EntityManager::getRepository(User::class)->findBy(['email' => 'test@example.com']);

Implementation Patterns

Workflows

  1. Entity Lifecycle:

    • Use EntityManager::persist() to schedule an entity for insertion.
    • Use EntityManager::remove() to mark an entity for deletion.
    • Always call EntityManager::flush() to synchronize changes with the database.
  2. Repositories:

    • Extend LaravelDoctrine\ORM\Repository\Repository for custom logic:
      namespace App\Repositories;
      
      use App\Models\User;
      use LaravelDoctrine\ORM\Repository\Repository;
      
      class UserRepository extends Repository
      {
          public function findActiveUsers(): array
          {
              return $this->createQueryBuilder('u')
                  ->where('u.isActive = :active')
                  ->setParameter('active', true)
                  ->getQuery()
                  ->getResult();
          }
      }
      
  3. QueryBuilder Integration:

    • Leverage Doctrine’s QueryBuilder for complex queries:
      $qb = EntityManager::getRepository(User::class)->createQueryBuilder('u');
      $qb->join('u.roles', 'r')
         ->where('r.name = :role')
         ->setParameter('role', 'admin');
      $admins = $qb->getQuery()->getResult();
      
  4. Transactions:

    • Wrap operations in transactions:
      EntityManager::getConnection()->beginTransaction();
      try {
          // Operations...
          EntityManager::getConnection()->commit();
      } catch (\Exception $e) {
          EntityManager::getConnection()->rollBack();
          throw $e;
      }
      

Integration Tips

  • Hybrid Eloquent/Doctrine: Use LaravelDoctrine\Eloquent\DoctrineEloquent to bridge Eloquent models with Doctrine entities.
  • Migrations: Use Doctrine Migrations (php artisan doctrine:migrations:diff) alongside Laravel migrations for schema changes.
  • Caching: Configure doctrine.cache in config/doctrine.php for query result caching (e.g., apcu, redis).

Gotchas and Tips

Pitfalls

  1. Lazy Loading:

    • Doctrine uses lazy loading by default. Accessing uninitialized associations triggers proxy instantiation. Use fetch="EAGER" or join in queries to avoid ProxyQueryException.
  2. Entity State Management:

    • Forgetting persist() or flush() leads to unsaved changes. Always verify state with EntityManager::isOpen() or EntityManager::getUnitOfWork()->getScheduledEntityInsertions().
  3. Case Sensitivity:

    • Doctrine is case-sensitive for entity/property names. Ensure annotations/metadata match class definitions exactly.
  4. Circular References:

    • Bidirectional associations (e.g., OneToMany + ManyToOne) require careful mappedBy/inversedBy configuration to avoid infinite loops.
  5. Transaction Isolation:

    • Long-running transactions may cause locks. Use SET TRANSACTION ISOLATION LEVEL READ COMMITTED in doctrine.event_listeners if needed.

Debugging

  • Enable SQL Logging:
    $config = EntityManager::getConfiguration();
    $config->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger());
    
  • Check Unit of Work:
    $uow = EntityManager::getUnitOfWork();
    print_r($uow->getScheduledEntityInsertions());
    
  • Validate Metadata:
    php artisan doctrine:schema:validate
    

Extension Points

  1. Custom Events:

    • Listen to Doctrine events via doctrine.event_dispatcher in config:
      'event_dispatcher' => [
          'listeners' => [
              'postPersist' => [
                  'App\Listeners\UserCreatedListener',
              ],
          ],
      ],
      
  2. Custom Types:

    • Extend Doctrine\DBAL\Types\Type for custom database types (e.g., JSON, enum).
  3. Hybrid Repositories:

    • Combine Eloquent and Doctrine queries in a single repository:
      use Illuminate\Support\Facades\DB;
      use LaravelDoctrine\ORM\Facades\EntityManager;
      
      class HybridUserRepository extends Repository
      {
          public function findByEmailOrRaw($email)
          {
              return EntityManager::getRepository(User::class)
                  ->findBy(['email' => $email])
                  ?? DB::table('users')->where('email', $email)->first();
          }
      }
      
  4. DQL vs. Native SQL:

    • Use EntityManager::createNativeQuery() for complex SQL not expressible in DQL:
      $query = EntityManager::createNativeQuery('SELECT * FROM users WHERE email = :email');
      $query->setParameter('email', 'test@example.com');
      $result = $query->getResult();
      

Config Quirks

  • Connection Names: Ensure orm.connection in config/doctrine.php matches your database connection name (e.g., mysql, pgsql).
  • Proxy Directory: Set orm.proxy_dir to a writable directory for generated proxy classes (e.g., storage/doctrine/proxy).
  • Metadata Drivers: Prefer yaml or xml for metadata if using annotations causes performance issues. Configure via orm.metadata_driver.
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.
daikazu/eloquent-salesforce-objects
unseen-codes/chat
romalytar/yammi-jobs-monitoring-laravel
kisame76/filament-db-table-state
nqxcode/laravel-lucene-search
dpfx/laravel-livewire-wizards
workos/workos-php-laravel
sofa/laravel-global-scope
nawasara/auth-primitives
adhocrat-io/arkhe-main
make-dev/orca-harpoon
itsemon245/lamet
baks-dev/dashboard
amoifr/pickle-panther-bundle
make-dev/orca
dmstr/symfony-system-resources-bundle
dmstr/symfony-job-queue-bundle
dmstr/openapi-json-schema-bundle
dmstr/keycloak-security-bundle
dmstr/doctrine-audit-log-bundle