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 built on Doctrine DBAL, providing transparent persistence for PHP objects. Use mappings, repositories, and Unit of Work, plus DQL for powerful, object-oriented querying as an alternative to SQL.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup in Laravel

  1. Installation:

    composer require doctrine/orm
    

    Laravel already includes Doctrine DBAL (dependency of ORM), so no extra DBAL installation is needed.

  2. Configuration: Doctrine ORM requires a config.yml or equivalent. In Laravel, use the doctrine/orm package with a custom config file (e.g., config/doctrine.php):

    return [
        'default_connection' => 'default',
        'connections' => [
            'default' => [
                'driver' => 'pdo_mysql',
                'host' => env('DB_HOST'),
                'port' => env('DB_PORT'),
                'dbname' => env('DB_DATABASE'),
                'user' => env('DB_USERNAME'),
                'password' => env('DB_PASSWORD'),
                'driverOptions' => [
                    PDO::MYSQL_ATTR_SSL_CA => env('DB_SSL_CA'),
                ],
            ],
        ],
        'entity_managers' => [
            'default' => [
                'connection' => 'default',
                'mappings' => [
                    'App' => [
                        'is_bundle' => false,
                        'type' => 'annotation',
                        'dir' => __DIR__.'/../app/Models',
                        'prefix' => 'App\Models',
                        'alias' => 'App',
                    ],
                ],
            ],
        ],
    ];
    
  3. First Use Case: Define an entity (e.g., app/Models/User.php) with Doctrine annotations:

    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: 180, unique: true)]
        private string $email;
    
        // Getters/setters...
    }
    

    Register the ORM in AppServiceProvider:

    public function boot()
    {
        $config = config('doctrine');
        $connection = Doctrine\DBAL\DriverManager::getConnection($config['connections']['default']);
        $entityManager = Doctrine\ORM\EntityManager::create($connection, $config['entity_managers']['default']);
        $this->app->singleton('doctrine.entity_manager', fn() => $entityManager);
    }
    

    Use the EntityManager in a service:

    $user = $this->app['doctrine.entity_manager']->find(User::class, 1);
    

Implementation Patterns

Common Workflows

  1. CRUD Operations:

    // Create
    $user = new User();
    $user->setEmail('[email protected]');
    $em->persist($user);
    $em->flush();
    
    // Read
    $user = $em->find(User::class, 1);
    $users = $em->getRepository(User::class)->findAll();
    
    // Update
    $user->setEmail('[email protected]');
    $em->flush();
    
    // Delete
    $em->remove($user);
    $em->flush();
    
  2. Querying with DQL:

    $query = $em->createQuery('SELECT u FROM App\Models\User u WHERE u.email LIKE :email')
        ->setParameter('email', '%test%');
    $results = $query->getResult();
    
  3. Repositories: Extend Doctrine\ORM\EntityRepository for custom logic:

    class UserRepository extends EntityRepository
    {
        public function findByEmail(string $email): ?User
        {
            return $this->findOneBy(['email' => $email]);
        }
    }
    
  4. Transactions:

    $em->beginTransaction();
    try {
        $em->persist($user);
        $em->flush();
        $em->commit();
    } catch (\Exception $e) {
        $em->rollback();
        throw $e;
    }
    
  5. Relationships: Define associations in entities:

    #[ORM\OneToMany(mappedBy: 'user', targetEntity: Post::class)]
    private Collection $posts;
    

Integration Tips

  • Laravel Eloquent Hybrid: Use Doctrine for complex queries and Eloquent for simplicity where possible.
  • Migrations: Combine with doctrine/dbal for schema migrations:
    $schemaTool = new \Doctrine\ORM\Tools\SchemaTool($em);
    $schemaTool->createSchema($em->getMetadataFactory()->getAllMetadata());
    
  • Caching: Enable query caching in config/doctrine.php:
    'entity_managers' => [
        'default' => [
            'query_cache_impl' => new \Doctrine\Common\Cache\ArrayCache(),
        ],
    ]
    

Gotchas and Tips

Pitfalls

  1. Lazy Loading: Doctrine loads relationships lazily by default. Use fetch="EAGER" or join in queries to avoid N+1 queries:

    #[ORM\ManyToOne(fetch: 'EAGER')]
    private ?User $author;
    
  2. Case Sensitivity: DQL is case-sensitive for identifiers. Use quotes for reserved keywords:

    $query = $em->createQuery('SELECT u FROM App\Models\User u WHERE u.id = :id');
    
  3. Connection Management: Ensure the connection is properly configured. Test with:

    $connection = $em->getConnection();
    $connection->getDatabasePlatform()->getSqlFormatter();
    
  4. Circular References: Avoid circular references in entity relationships (e.g., UserPostUser). Use inversedBy/mappedBy carefully.

  5. Transaction Isolation: Long-running transactions can lock tables. Use shorter transactions or read-committed isolation:

    $connection->beginTransaction(Connection::TRANSACTION_READ_COMMITTED);
    

Debugging

  • SQL Logging: Enable SQL logging in config/doctrine.php:

    'entity_managers' => [
        'default' => [
            'logging' => true,
            'connection' => [
                'logging' => true,
                'driver' => 'pdo_mysql',
                'driverOptions' => [
                    PDO::MYSQL_ATTR_LOG_QUERY => true,
                ],
            ],
        ],
    ]
    

    Check logs in storage/logs/laravel.log.

  • Query Profiling: Use the Doctrine\ORM\Query\Query profiler:

    $query->useResultCache(true);
    $query->useQueryCache(true);
    

Tips

  1. Hybrid Approach: Use Doctrine for complex queries and Eloquent for simple ones. Example:

    // Doctrine DQL
    $query = $em->createQuery('SELECT u FROM App\Models\User u WHERE u.createdAt > :date')
        ->setParameter('date', new \DateTime('-1 week'));
    
    // Eloquent
    $users = User::where('created_at', '>', now()->subWeek())->get();
    
  2. Custom DQL Functions: Register custom DQL functions in config/doctrine.php:

    'entity_managers' => [
        'default' => [
            'dql' => [
                'string_functions' => [
                    'CONCAT' => 'DoctrineExtensions\Query\Mysql\Concat',
                ],
            ],
        ],
    ]
    
  3. Event Listeners: Use Doctrine events for pre/post operations:

    $em->getEventManager()->addEventListener(
        \Doctrine\ORM\Events::prePersist,
        function ($event) {
            $entity = $event->getEntity();
            if ($entity instanceof User) {
                $entity->setUpdatedAt(new \DateTime());
            }
        }
    );
    
  4. Second-Level Cache: Enable for read-heavy applications:

    $em->getConfiguration()->setSecondLevelCacheEnabled(true);
    $em->getConfiguration()->setSecondLevelCacheRegion('default');
    
  5. Laravel Service Container: Bind the EntityManager as a singleton for dependency injection:

    $this->app->bind('doctrine.entity_manager', fn() => $em);
    

    Then inject it into controllers/services:

    public function __construct(private EntityManager $em) {}
    
  6. Schema Validation: Validate your schema before migrations:

    $schemaTool = new \Doctrine\ORM\Tools\SchemaTool($em);
    $schemaTool->updateSchema($em->getMetadataFactory()->getAllMetadata(), true);
    
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.
calmfox/watch-sylius
damienfern/grpc-symfony-bundle
atoolo/index-bundle
atoolo/genai-bundle
coprotoai/laravel-ticket
davidjln/llm-carbon-bundle
cryonighter/valid-request-bundle
coolms/taxonomy-bundle
coolms/field-bundle
articulate-orm/symfony
aaix/laravel-tall-architect
ephoto/akeneo-connector
emmanuelballery/eb-plantumlbundle
emielburgman/symfony-visitor-beacon
emielburgman/symfony-visit-storage
emielburgman/symfony-security-headers
emielburgman/symfony-log-viewer
emarref/xdebug-bundle
emarref/pubnub-bundle
elriseio/finance-money-bundle