anh/doctrine-resource-bundle
Installation
composer require anh/doctrine-resource-bundle
Add the bundle to config/bundles.php in Symfony:
Anh\DoctrineResourceBundle\AnhDoctrineResourceBundle::class => ['all' => true],
First Use Case: Basic CRUD with Doctrine Extensions
anh/doctrine-extensions-resource is installed (dependency).Sluggable, Timestampable).src/Entity/Article.php):
use Gedmo\Mapping\Annotation as Gedmo;
/**
* @Gedmo\Slug(fields={"title"})
*/
class Article { ... }
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
Symfony Integration
anh.doctrine_resource.manager) to handle Doctrine extensions via Symfony’s DI container.use Anh\DoctrineResourceBundle\Manager\ResourceManager;
class ArticleController {
public function __construct(private ResourceManager $resourceManager) {}
public function update(Article $article) {
$this->resourceManager->update($article); // Triggers extensions (e.g., slug update)
}
}
Lifecycle-Centric Development
Timestampable or Blameable (via anh/doctrine-extensions-resource).
// src/Entity/User.php
use Gedmo\Mapping\Annotation as Gedmo;
/**
* @Gedmo\Timestampable(on="create")
*/
class User { ... }
Translatable).
$user = $entityManager->find(User::class, 1);
$this->resourceManager->refresh($user); // Ensures translations are loaded
Symfony Form Integration
Sluggable:
// src/Form/ArticleType.php
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Anh\DoctrineResourceBundle\Form\Extension\ResourceTypeExtension;
$builder->add('title', TextType::class);
$builder->add('slug', TextType::class, [
'mapped' => false, // Slug is auto-generated
]);
ResourceTypeExtension in services.yaml:
services:
Anh\DoctrineResourceBundle\Form\Extension\ResourceTypeExtension:
tags: [form.type_extension]
Event-Driven Extensions
Auditable extension.
// src/EventListener/AuditListener.php
use Anh\DoctrineResourceBundle\Event\ResourceEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class AuditListener implements EventSubscriberInterface {
public static function getSubscribedEvents() {
return [
ResourceEvent::PRE_PERSIST => 'logChange',
ResourceEvent::PRE_UPDATE => 'logChange',
];
}
public function logChange(ResourceEvent $event) {
// Custom audit logic
}
}
orm.xml or annotations are properly configured for extensions.
<!-- config/doctrine/orm.xml -->
<doctrine-mapping
xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<driver name="annotations" path="src/Entity"/>
</doctrine-mapping>
php bin/console cache:clear
ResourceManager in functional tests to verify extensions:
$this->getContainer()->get('anh.doctrine_resource.manager')->update($entity);
$this->assertEquals('expected-slug', $entity->getSlug());
Extension Conflicts
Sluggable + Translatable) may override each other.@Gedmo\OrderBy or custom event listeners to prioritize logic.
// src/EventListener/SlugPriorityListener.php
use Anh\DoctrineResourceBundle\Event\ResourceEvent;
class SlugPriorityListener {
public function onPrePersist(ResourceEvent $event) {
if ($event->getEntity() instanceof Article) {
$this->resourceManager->generateSlug($event->getEntity());
}
}
}
Missing Dependencies
anh/doctrine-extensions-resource (required by the bundle).composer.json includes:
"require": {
"anh/doctrine-extensions-resource": "^0.4"
}
Cache Invalidation
php bin/console doctrine:cache:clear-metadata
Form Mapping Quirks
mapped => false fields (e.g., auto-generated slugs) may still appear in forms.ArticleType:
$builder->remove('slug'); // If auto-generated
# config/packages/dev/doctrine.yaml
doctrine:
dbal:
logging: true
profiling: true
php bin/console debug:event-dispatcher
$metadata = $entityManager->getClassMetadata(Article::class);
dump($metadata->getLifecycleCallbacks());
Custom Events
ResourceEvent for domain-specific logic:
class CustomResourceEvent extends ResourceEvent {
public function setCustomData($data) { ... }
}
$dispatcher->dispatch(new CustomResourceEvent($entity, $eventName));
Dynamic Configuration
config/packages/anh_doctrine_resource.yaml:
anh_doctrine_resource:
extensions:
slug:
fields: ['title', 'subtitle'] # Custom slug fields
Performance Optimization
$this->resourceManager->bulkUpdate([$entity1, $entity2]);
$this->resourceManager->setLazyLoading(true);
How can I help you explore Laravel packages today?