doctrine/mongodb-odm-bundle
Symfony bundle integrating Doctrine MongoDB ODM for mapping PHP documents to MongoDB. Provides configuration, DI services, console commands, and tooling to manage connections, document managers, and repositories in Symfony apps.
Installation Add the bundle via Composer:
composer require doctrine/mongodb-odm-bundle
Enable it in config/bundles.php:
return [
// ...
Doctrine\Bundle\MongoDBBundle\DoctrineMongoDBBundle::class => ['all' => true],
];
Configuration
Define your MongoDB connection in config/packages/doctrine_mongodb.yaml:
doctrine_mongodb:
connections:
default:
uri: '%env(MONGODB_URI)%'
options: {}
document_managers:
default:
connection: default
mappings:
App:
type: attribute
dir: '%kernel.project_dir%/src/Document'
prefix: 'App\Document'
alias: App
First Document Model
Create a document class with the #[Document] attribute:
// src/Document/User.php
namespace App\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
#[ODM\Document(collection: "users")]
class User
{
#[ODM\Id]
private ?string $id = null;
#[ODM\Field(type: "string")]
private string $name;
// Getters/setters...
}
First Query
Use the DocumentManager in a service or controller:
use Doctrine\ODM\MongoDB\DocumentManager;
public function __construct(private DocumentManager $dm) {}
public function findUser(string $id): ?User
{
return $this->dm->find(User::class, $id);
}
$user = new User();
$user->setName('John Doe');
$this->dm->persist($user);
$this->dm->flush();
$user = $this->dm->find(User::class, $id);
$users = $this->dm->getRepository(User::class)->findAll();
$user->setName('Updated Name');
$this->dm->flush();
$this->dm->remove($user);
$this->dm->flush();
Use Criteria for complex queries:
use Doctrine\ODM\MongoDB\Query\Criteria;
$criteria = Criteria::create()
->where(Criteria::expr()->eq('name', 'John Doe'))
->limit(10);
$query = $this->dm->createQueryBuilder(User::class)
->field('name')->equals('John Doe')
->hydrate(false)
->getQuery();
$results = $query->execute();
Extend DocumentRepository for custom logic:
namespace App\Repository;
use App\Document\User;
use Doctrine\ODM\MongoDB\Repository\DocumentRepository;
class UserRepository extends DocumentRepository
{
public function findByName(string $name): array
{
return $this->createQueryBuilder(User::class)
->field('name')->equals($name)
->getQuery()
->execute();
}
}
Use Transaction for atomic operations:
$this->dm->beginTransaction();
try {
// Operations...
$this->dm->commit();
} catch (\Exception $e) {
$this->dm->rollback();
throw $e;
}
Define relationships with #[EmbeddedDocument]:
#[ODM\EmbeddedDocument]
class Address
{
#[ODM\Field(type: "string")]
private string $street;
// ...
}
#[ODM\Document]
class User
{
#[ODM\EmbeddedOne(targetDocument: Address::class)]
private Address $address;
}
Use #[ReferenceOne] or #[ReferenceMany]:
#[ODM\Document]
class Post
{
#[ODM\ReferenceOne(targetDocument: User::class)]
private ?User $author = null;
}
Use annotations like #[ODM\PrePersist]:
#[ODM\Document]
class User
{
#[ODM\PrePersist]
public function prePersist(): void
{
$this->createdAt = new \DateTime();
}
}
Load test data with doctrine:mongodb:fixtures:load:
# config/packages/doctrine_mongodb.yaml
doctrine_mongodb:
document_managers:
default:
fixtures:
paths:
- '%kernel.project_dir%/src/DataFixtures/MongoDB'
// src/DataFixtures/MongoDB/UserFixture.php
namespace App\DataFixtures\MongoDB;
use App\Document\User;
use Doctrine\Bundle\MongoDBBundle\Fixture\FixtureInterface;
use Doctrine\Bundle\MongoDBBundle\Fixture\ServiceContainerAwareFixtureInterface;
use Doctrine\ODM\MongoDB\DocumentManager;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class UserFixture implements FixtureInterface, ServiceContainerAwareFixtureInterface, ContainerAwareInterface
{
private DocumentManager $dm;
private ContainerInterface $container;
public function setContainer(ContainerInterface $container = null): void
{
$this->container = $container;
}
public function load(ObjectManager $dm): void
{
$this->dm = $dm;
$user = new User();
$user->setName('Fixture User');
$dm->persist($user);
$dm->flush();
}
}
Use MongoDBObject for form fields:
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('name', TextType::class);
}
Annotate documents with #[ApiResource]:
use ApiPlatform\Metadata\ApiResource;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
#[ApiResource]
#[ODM\Document]
class User
{
// ...
}
Subscribe to ODM events:
use Doctrine\ODM\MongoDB\Event\LifecycleEventArgs;
public function prePersist(LifecycleEventArgs $args): void
{
$document = $args->getDocument();
if ($document instanceof User) {
$document->setUpdatedAt(new \DateTime());
}
}
Use Hydrator for custom serialization:
use Doctrine\ODM\MongoDB\Hydrator\HydratorInterface;
class CustomHydrator implements HydratorInterface
{
public function hydrate(array $data, $document): void
{
// Custom logic...
}
}
Use GridFS for large files:
use Doctrine\ODM\MongoDB\GridFS\GridFS;
$gridFS = $this->dm->getGridFS();
$file = $gridFS->storeFile($fileContent, ['metadata' => ['user_id' => $user->getId()]]);
strict: true in mappings for validation:
doctrine_mongodb:
document_managers:
default:
mappings:
App:
type: attribute
dir: '%kernel.project_dir%/src/Document'
prefix: 'App\Document'
strict: true # Enforce schema validation
doctrine_mongodb:
document_managers:
default:
lazy_ghost_objects: true # Default in v5.5+
lazy_ghost_objects: false
_id by defaultHow can I help you explore Laravel packages today?