chaplean/doctrine-extensions-bundle
## Getting Started
### Minimal Setup for Laravel (Adapted)
Since this bundle is Symfony-focused, Laravel developers must manually integrate its dependencies (`gedmo/doctrine-extensions`). Start here:
1. **Install Dependencies**
```bash
composer require gedmo/doctrine-extensions
Configure Doctrine ORM
Add mappings to config/packages/doctrine.yaml (or config/doctrine.php in Laravel 8+):
doctrine:
orm:
mappings:
GedmoTranslatable:
type: annotation
prefix: Gedmo\Translatable\Entity
dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/lib/Gedmo/Translatable/Entity"
GedmoLoggable:
type: annotation
prefix: Gedmo\Loggable\Entity
dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/lib/Gedmo/Loggable/Entity"
GedmoTree:
type: annotation
prefix: Gedmo\Tree\Entity
dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/lib/Gedmo/Tree/Entity"
First Use Case: Translatable Entities
Annotate a model (e.g., Post) with @Gedmo\Translatable and define translatable fields:
use Gedmo\Mapping\Annotation as Gedmo;
class Post
{
/**
* @Gedmo\Translatable
*/
private $title;
/**
* @Gedmo\Locale
*/
private $locale;
}
Use Translation listener in bootstrap/app.php:
$app->make('doctrine')->getManager()->getEventManager()->addEventSubscriber(
new \Gedmo\Translatable\TranslatableListener()
);
Translatable Entities:
@Gedmo\Translatable on fields needing translations (e.g., title, description).translation).getTranslations() or getTranslation('en').$post = new Post();
$post->setTitle('Titre'); // French
$post->setLocale('fr');
$entityManager->persist($post);
$entityManager->flush();
// Later, fetch English translation
$englishTitle = $post->getTranslation('en')->getTitle(); // Returns NULL if missing
Loggable Entities:
@Gedmo\Loggable.log_entry table by default.$user = new User();
$user->setEmail('old@example.com');
$entityManager->persist($user);
$entityManager->flush();
$user->setEmail('new@example.com');
$entityManager->flush();
// Fetch logs
$logs = $entityManager->getRepository(LogEntry::class)
->findBy(['objectClass' => User::class]);
Tree Entities:
@Gedmo\TreeType.getChildren(), getParent(), and getRoot() simplify traversal.$category = new Category();
$category->setName('Electronics');
$entityManager->persist($category);
$laptopCategory = new Category();
$laptopCategory->setParent($category);
$laptopCategory->setName('Laptops');
$entityManager->persist($laptopCategory);
// Fetch children
$children = $category->getChildren(); // Returns Collection of Category
Translatable Queries:
Use Gedmo\Translatable\Query\TreeWalker\TranslationWalker to filter by locale:
$qb = $entityManager->createQueryBuilder();
$qb->select('p')
->from(Post::class, 'p')
->where('p.translations LIKE :locale')
->setParameter('locale', '%en%');
Tree Queries: Query subtrees or siblings:
// Get all descendants of a node
$descendants = $entityManager->getRepository(Category::class)
->createQueryBuilder('c')
->where('c.lft BETWEEN :lft AND :rgt')
->setParameter('lft', $category->getLft())
->setParameter('rgt', $category->getRgt())
->getQuery()
->getResult();
Service Providers:
Register listeners in AppServiceProvider:
public function boot()
{
$this->app->make('doctrine')->getManager()->getEventManager()->addEventSubscriber(
new \Gedmo\Translatable\TranslatableListener()
);
$this->app->make('doctrine')->getManager()->getEventManager()->addEventSubscriber(
new \Gedmo\Loggable\LoggableListener()
);
$this->app->make('doctrine')->getManager()->getEventManager()->addEventSubscriber(
new \Gedmo\Tree\TreeListener()
);
}
Eloquent Compatibility:
Use doctrine/orm alongside illuminate/database by configuring Laravel’s EntityManager in config/database.php:
'doctrine' => [
'entity_manager' => 'default',
],
Locale Handling:
locale field when saving translatable entities. Missing locales will cause NULL translations.prePersist lifecycle callback:
use Gedmo\Mapping\Annotation as Gedmo;
class Post
{
/**
* @Gedmo\Locale
*/
private $locale;
public function prePersist()
{
if (empty($this->locale)) {
$this->locale = app()->getLocale(); // Fallback to app locale
}
}
}
Tree Entities:
parent) outside Doctrine’s context will break the tree structure. Always use persist()/merge().MaterializedPath or NestedSet strategies wisely.parent ↔ children) that could cause infinite loops in serialization.Loggable Entities:
log_entry table exists and matches the schema (run doctrine:schema:update if needed).$entityManager->getEventManager()->removeEventSubscriber(
$entityManager->getEventManager()->getEventSubscriber('gedmo_loggable')
);
Translatable Debugging:
translation table directly:
SELECT * FROM translation WHERE object_class = 'App\Entity\Post';
locale field is set correctly.Tree Debugging:
lft/rgt or path values in the database to debug hierarchy issues.Gedmo\Tree\TreeType::MATERIALIZED_PATH for easier debugging of paths.Loggable Debugging:
INSERT/UPDATE queries for log_entry:
$entityManager->getConnection()->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger());
Mapping Directories:
config.yml may break if vendor paths change. Use %kernel.project_dir% (Symfony) or Laravel’s base_path():
dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/lib/Gedmo/Translatable/Entity"
Laravel equivalent:
dir: base_path('vendor/gedmo/doctrine-extensions/lib/Gedmo/Translatable/Entity')
Event Subscribers:
booted() in AppServiceProvider:How can I help you explore Laravel packages today?