Installation
composer require doctrine/couchdb-odm:^1.0.0-alpha3
Note: This is an alpha release—test thoroughly in a staging environment. Laravel does not natively support Doctrine ODM, so manual configuration is required.
Configure CouchDB Connection
Add to config/services.php:
'couchdb' => [
'host' => env('COUCHDB_HOST', 'http://localhost:5984'),
'username' => env('COUCHDB_USER'),
'password' => env('COUCHDB_PASS'),
'timeout' => env('COUCHDB_TIMEOUT', 30), // New in alpha3: Configurable timeout
],
First Document Model
Extend \Doctrine\ODM\CouchDB\Mapping\Document with updated annotations (ensure doctrine/annotations is installed):
namespace App\Documents;
use Doctrine\ODM\CouchDB\Mapping\Annotations as ODM;
/** @ODM\Document(repositoryClass="App\Repositories\UserRepository") */
class User {
/** @ODM\Id(strategy="UUID") */ // New: UUID strategy support
public $id;
/** @ODM\Field(type="string") */
public $name;
/** @ODM\Field(type="email") */
public $email;
/** @ODM\Embedded(class="App\Documents\Address") */
public $address;
}
Initialize ODM in a Service Provider
Updated for alpha3’s breaking changes (e.g., CouchDBManager constructor):
use Doctrine\ODM\CouchDB\CouchDBManager;
public function boot() {
$config = $this->app['config']['services.couchdb'];
$conn = \Doctrine\ODM\CouchDB\Connection::create(
$config['host'],
$config['username'] ?? null,
$config['password'] ?? null,
['timeout' => $config['timeout'] ?? 30]
);
$this->app->singleton('couchdb.manager', function () use ($conn) {
return CouchDBManager::create($conn, [
'document_managers' => ['default' => [
'mappings' => [__DIR__.'/Documents'],
'repository_factory' => new \Doctrine\ODM\CouchDB\Repository\DefaultRepositoryFactory(), // Explicit factory
]]
]);
});
}
First Query
$dm = app('couchdb.manager')->getDocumentManager();
$user = $dm->find('App\Documents\User', 'some_id');
CRUD Operations
// Create with UUID (new in alpha3)
$user = new User();
$user->id = \Ramsey\Uuid\Uuid::uuid4()->toString(); // Requires `ramsey/uuid`
$user->name = 'John';
$user->email = 'john@example.com';
$dm->persist($user);
$dm->flush();
Querying with DQL
$query = $dm->createQuery('SELECT u FROM App\Documents\User u WHERE u.email LIKE :email')
->setParameter('email', '%@example.com');
$users = $query->getResult();
Bulk Operations with Batch Processing
$batchSize = 50;
for ($i = 0; $i < 1000; $i += $batchSize) {
$batch = array_slice($users, $i, $batchSize);
$dm->persistAll($batch);
$dm->flush();
}
Event Listeners (Updated for Alpha3) Register listeners with the new event manager API:
$dm->getEventManager()->addEventSubscriber(
new \App\Listeners\UserAuditSubscriber()
);
Migrations via Design Documents
Use the new DesignDocument class for schema management:
$designDoc = new \Doctrine\ODM\CouchDB\DesignDocument('user');
$designDoc->addView('by_email', 'function(doc) { if (doc.type === "User") emit(doc.email, doc); }');
$dm->getConnection()->createDesignDocument($designDoc);
Breaking Changes in Alpha3
CouchDBManager::create() now requires an array for options.Id strategy is now UUID (not auto-increment). Install ramsey/uuid:
composer require ramsey/uuid
CouchDBManager::getConnection() is replaced with $dm->getConnection().No Native Laravel Integration
_design docs or third-party tools like couchdb-migrate.Performance Quirks
?stale=update_after for consistency.Annotation Parsing
doctrine/annotations is installed:
composer require doctrine/annotations
$dm->getConfiguration()->setMetadataCacheImpl(
new \Doctrine\Common\Cache\FilesystemCache(__DIR__.'/../var/cache')
);
Enable Verbose Logging
$dm->getConfiguration()->setSQLLogger(new \Doctrine\Common\Log\DebugStack());
$dm->getConfiguration()->setQueryLogger(new \Doctrine\Common\Log\DebugStack());
Check CouchDB Fauxton UI
http://localhost:5984/_utils._design docs for view definitions.Handle Exceptions Wrap operations in try-catch:
try {
$dm->flush();
} catch (\Doctrine\ODM\CouchDB\Exception\CouchDBException $e) {
\Log::error('CouchDB Error: ' . $e->getMessage());
// Retry logic or fallback
}
Custom Hydrators
Extend \Doctrine\ODM\CouchDB\Hydrator\ObjectHydrator for custom serialization:
class CustomHydrator extends ObjectHydrator {
public function hydrate($data, $class) {
// Custom logic
return parent::hydrate($data, $class);
}
}
Event Subscribers
Implement \Doctrine\Common\EventSubscriber for lifecycle hooks:
class UserAuditSubscriber implements EventSubscriber {
public function getSubscribedEvents() {
return ['prePersist', 'preUpdate'];
}
public function prePersist(LifecycleEventArgs $args) {
$user = $args->getDocument();
$user->updatedAt = new \DateTime();
}
}
Custom Repositories
namespace App\Repositories;
use Doctrine\ODM\CouchDB\DocumentRepository;
class UserRepository extends DocumentRepository {
public function findByEmail($email) {
return $this->createQueryBuilder('u')
->where('u.email = :email')
->setParameter('email', $email)
->getQuery()
->getSingleResult();
}
}
Raw CouchDB Access Use the underlying connection for low-level operations:
$conn = $dm->getConnection();
$result = $conn->createQuery('SELECT * FROM users WHERE email = "test@example.com"')
->setOption('include_docs', true)
->execute();
Embedded Documents
Leverage the new @ODM\Embedded annotation for nested structures:
/** @ODM\Embedded */
class Address {
/** @ODM\Field */
public $street;
}
How can I help you explore Laravel packages today?