ruvents/doctrine-bundle
A Symfony bundle that integrates Doctrine ORM by registering entity managers, database connections, and mapping configuration. It provides default services and config for Doctrine-backed applications, simplifying persistence setup.
composer require ruvents/doctrine-bundle. On Laravel 5.5+ the service provider is auto-discovered; on older versions register Ruvents\DoctrineBundle\DoctrineServiceProvider manually in config/app.php.php artisan vendor:publish --provider="Ruvents\DoctrineBundle\DoctrineServiceProvider". This gives you the config/doctrine.php-style file where you define connections, the metadata driver (annotation, xml, or yaml), proxy directory, and cache backend.EntityManager binding and how it reads config keys. Read it before trusting any tutorial you find online.app/Entities, point the metadata driver at that namespace, and confirm the EntityManager resolves and can persist()/flush() it. For example, a User entity with a @ORM\Entity annotation and a matching repository class, then fetch it with $em->getRepository(User::class)->findAll().doctrine:schema:create, doctrine:schema:update, doctrine:migrations:* depending on what the provider wires up) show up in php artisan list before writing code. If they don't, the config is wrong, not the commands.EntityManager into services, not controllers. The bundle binds it on the container, so a constructor type-hint is the cleanest integration. Keep controllers thin: one call into a service that owns the unit of work.repositoryClass and expose named finder methods (findActiveForAccount()). This mirrors the "custom repositories" feature and keeps DQL out of your application layer.flush() once, wrap multi-step operations in $em->transactional(fn () => ...). Avoid calling flush() inside loops — batch and flush per unit of work.database.connections entry by name in the Doctrine config rather than duplicating credentials, but treat the two persistence layers as separate schemas-of-record. Do not write the same table from both.doctrine:schema:validate in CI and generate schema diffs in code review. Because the bundle predates modern migration tooling, most teams drive schema from entity metadata and treat Eloquent migrations as unrelated infrastructure (jobs, cache, etc.).EntityManager against an in-memory SQLite connection in your base TestCase, create the schema once, and truncate between tests. Mock the manager only for pure unit tests of services; integration tests should exercise real flush/identity-map behavior."ruvents/doctrine-bundle": "0.2.2"), commit the lock file, and plan an exit path. The most realistic alternative is wiring Doctrine ORM directly in a small service provider — it's a couple hundred lines and removes a dead dependency from a critical path.doctrine/orm and doctrine/annotations. On PHP 8+, annotations are deprecated and doctrine/annotations reading order/case changed. Expect to need to bump transitive Doctrine packages, and expect the bundle's provider to break when you do. Test the upgrade on a branch.rm -rf) when entity mappings change in development.php artisan config:clear && php artisan cache:clear — and if you cache the metadata (recommended for production), invalidate it on deploy. Stale metadata caches are the #1 source of "why is my new field ignored" bugs.saving/saved hooks or Model::factory(). Use Doctrine lifecycle callbacks (@PrePersist, @PreUpdate) or EventSubscriber registrations through the config; factories must be hand-rolled.$em->createQuery('DELETE ...')->execute() or a DQL update, the in-memory entities are stale. Call $em->clear() (and refresh entities you still need) or you will persist wrong data silently.migrations table and you also run Eloquent migrations, configure a distinct table name in the Doctrine config. Otherwise one system will see the other's rows as unknown migrations.SQLLogger ($em->getConnection()->getConfiguration()->setSQLLogger(...)) or an EventSubscriber on postFlush/onFlush in local dev. Dump DQL via $query->getSQL() before executing when a QueryException is opaque.vendor/ruvents/doctrine-bundle/src against the version you upgraded from — that's faster than reading release notes that barely exist.EventSubscribers, and custom repository classes are all wired through config and are the supported ways to bend behavior. Do not subclass or copy the provider's bootstrapping into your AppServiceProvider; that couples you to internals and makes the eventual migration off the bundle much harder.How can I help you explore Laravel packages today?