axstrad/doctrine-extensions-bundle
Installation:
composer require axstrad/doctrine-extensions-bundle
Ensure your composer.json meets the package's PHP/Doctrine/Symfony version constraints (e.g., PHP ≥5.4, Doctrine ORM ~2.3, Symfony ≥2.3 <2.7).
Enable the Bundle:
Add to config/bundles.php:
return [
// ...
Axstrad\DoctrineExtensionsBundle\AxstradDoctrineExtensionsBundle::class => ['all' => true],
];
First Use Case:
Use the Sluggable behavior to auto-generate SEO-friendly URLs for entities. Example:
use Axstrad\DoctrineExtensions\Sluggable\Sluggable;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\HasLifecycleCallbacks
* @Sluggable(fields={"title"}, unique=true)
*/
class Article
{
// ...
}
$article = new Article();
$article->setTitle("My Awesome Article");
$em->persist($article);
$em->flush(); // Slug auto-generated
Sluggable Behavior:
fields to specify which fields generate the slug (e.g., fields={"title", "subtitle"}).- with separator="_" in the @Sluggable annotation.$entity->updateSlug() to regenerate slugs post-update.Timestampable Behavior:
createdAt/updatedAt without manual updates:
use Axstrad\DoctrineExtensions\Timestampable\Timestampable;
/**
* @Timestampable
*/
class Product {}
createdAt="customCreated" updatedAt="customUpdated" to map to custom properties.Soft-Deletable Behavior:
deletedAt field:
use Axstrad\DoctrineExtensions\SoftDeletable\SoftDeletable;
/**
* @SoftDeletable(deletedAt="deletedAt")
*/
class User {}
$em->getRepository(User::class)->findAll(); // Excludes deleted
$em->getRepository(User::class)->findAll(['withDeleted' => true]); // Includes deleted
Integration with Forms:
Symfony\Component\Form\Extension\Core\Type\TextType for slug fields with validation:
$builder->add('slug', TextType::class, [
'required' => false,
'error_bubbling' => true,
]);
Axstrad\DoctrineExtensions\Sluggable\SluggableListener to modify slug generation (e.g., add prefixes/suffixes).prePersist/preUpdate to conditionally trigger behaviors (e.g., skip slug generation for drafts):
$entity->getSlug() === null && $entity->updateSlug();
Version Conflicts:
doctrine/orm version aligns (e.g., ~2.3).composer.json if using newer Symfony/Doctrine:
"doctrine/orm": "2.3.*",
"symfony/symfony": "2.6.*"
Slug Uniqueness:
unique=true option in @Sluggable may fail if the slug generator doesn’t handle collisions (e.g., appending -1, -2).Soft Deletes + Queries:
withDeleted in queries returns no results for soft-deleted entities.public function findAllWithDeleted($withDeleted = false) {
return $this->createQueryBuilder('u')
->andWhere($withDeleted ? '' : 'u.deletedAt IS NULL')
->getQuery()
->getResult();
}
Lifecycle Callback Order:
flush() calls may bypass them.prePersist/preUpdate events or ensure flush() is called after setting properties.Enable SQL Logging:
$em->getConnection()->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger());
Verify soft-deletes or slug updates appear in queries.
Check Listener Registration:
Ensure the bundle’s listeners (e.g., SluggableListener) are registered. Debug with:
$container->has('axstrad.doctrine_extensions.sluggable.listener');
Custom Behaviors:
Axstrad\DoctrineExtensions\AbstractBehavior to create reusable logic (e.g., Hashable for password hashing).Override Defaults:
config/packages/axstrad_doctrine_extensions.yaml:
axstrad_doctrine_extensions:
sluggable:
separator: '_'
fields: ['title', 'subtitle'] # Global defaults
Event Dispatching:
axstrad.doctrine_extensions.slug.generate to intercept slug generation:
$dispatcher->addListener(
'axstrad.doctrine_extensions.slug.generate',
function ($event) {
$event->setSlug(strtoupper($event->getSlug()));
}
);
php bin/console doctrine:query-sql "UPDATE article SET slug = sluggable_generate('title') WHERE slug IS NULL"
deletedAt for faster queries:
ALTER TABLE user ADD INDEX idx_deleted_at (deletedAt);
How can I help you explore Laravel packages today?