From 396c124b2b8b7438c7fcfaf6c6ee4d8afad10471 Mon Sep 17 00:00:00 2001 From: Michael Babker Date: Sun, 30 Jun 2024 12:57:12 -0400 Subject: [PATCH 1/6] Move the framework integration guides into a folder for better discoverability --- README.md | 4 ++-- doc/{ => frameworks}/laminas.md | 2 +- doc/{ => frameworks}/symfony.md | 0 3 files changed, 3 insertions(+), 3 deletions(-) rename doc/{ => frameworks}/laminas.md (98%) rename doc/{ => frameworks}/symfony.md (100%) diff --git a/README.md b/README.md index 774737c540..d593761f14 100644 --- a/README.md +++ b/README.md @@ -28,9 +28,9 @@ flushed in a behavioral way. composer require gedmo/doctrine-extensions -* [Symfony](/doc/symfony.md) +* [Symfony](/doc/frameworks/symfony.md) * [Laravel 5](https://www.laraveldoctrine.org/docs/1.3/extensions) -* [Laminas](/doc/laminas.md) +* [Laminas](/doc/frameworks/laminas.md) ### Upgrading diff --git a/doc/laminas.md b/doc/frameworks/laminas.md similarity index 98% rename from doc/laminas.md rename to doc/frameworks/laminas.md index 6f02884923..5f68eb25b6 100644 --- a/doc/laminas.md +++ b/doc/frameworks/laminas.md @@ -44,7 +44,7 @@ return array( ); ``` -That's it! From now on you can use Gedmo annotations, just as it is described in [documentation](./annotations.md). +That's it! From now on you can use Gedmo annotations, just as it is described in [documentation](../annotations.md). #### Note: You may need to provide additional settings for some of the available listeners. diff --git a/doc/symfony.md b/doc/frameworks/symfony.md similarity index 100% rename from doc/symfony.md rename to doc/frameworks/symfony.md From 72d3242502abe27a7dfd76b470e4d15f8855946e Mon Sep 17 00:00:00 2001 From: Michael Babker Date: Sun, 30 Jun 2024 16:56:38 -0400 Subject: [PATCH 2/6] Rewrite the Symfony integration guide --- doc/frameworks/symfony.md | 755 +++++++++++++++++--------------------- 1 file changed, 337 insertions(+), 418 deletions(-) diff --git a/doc/frameworks/symfony.md b/doc/frameworks/symfony.md index 40acf432fb..9b3279fdba 100644 --- a/doc/frameworks/symfony.md +++ b/doc/frameworks/symfony.md @@ -1,218 +1,118 @@ -# Install Gedmo Doctrine extensions in Symfony +# Integrate the Doctrine Extensions in Symfony -Configure full featured [Doctrine extensions](https://github.com/doctrine-extensions/DoctrineExtensions) for your Symfony project. -This post will show you - how to create a simple configuration file to manage extensions with -ability to use all features it provides. -Interested? then bear with me! and don't be afraid, we're not diving into security component :) +This guide will demonstrate how to integrate the Doctrine Extensions library into a Symfony application. -This post will put some light over the shed of extension installation and mapping configuration -of Doctrine. It does not require any additional dependencies and gives you full power -over management of extensions. +> [!TIP] +> We recommend using the [`StofDoctrineExtensionsBundle`](https://symfony.com/bundles/StofDoctrineExtensionsBundle/current/index.html) which handles this integration for you. -Content: +## Index -- [Symfony](#sf-app) application -- Extensions metadata [mapping](#ext-mapping) -- Extensions filters [filtering](#ext-filtering) -- Extension [listeners](#ext-listeners) -- Usage [example](#ext-example) -- Some [tips](#more-tips) -- [Alternative](#alternative) over configuration +- [Getting Started](#getting-started) +- [Registering Extension Listeners](#registering-extension-listeners) +- [Registering Mapping Configuration](#registering-mapping-configuration) +- [Registering Filters](#registering-filters) +- [Configuring Extensions via Event Subscribers](#configuring-extensions-via-event-subscribers) - +## Getting Started -## Symfony application +Assuming you have already [created your Symfony application](https://symfony.com/doc/current/getting_started/index.html), +the next step will be to ensure you've installed this library and the Doctrine libraries you will need. -First of all, we will need a symfony startup application, let's say [symfony-standard edition -with composer](https://symfony.com/doc/current/best_practices/creating-the-project.html) +For Doctrine MongoDB ODM users, this Composer command will install all required dependencies: -- `composer create-project symfony/skeleton [project name]` - -Now let's add the **gedmo/doctrine-extensions** - -You can find the doctrine-extensions project on packagist: https://packagist.org/packages/gedmo/doctrine-extensions - -To add it to your project: -- `composer require gedmo/doctrine-extensions` - - - -## Mapping - -Let's start from the mapping. In case you use the **translatable**, **tree** or **loggable** -extension you will need to map those abstract mapped superclasses for your ORM to be aware of. -To do so, add some mapping info to your **doctrine.orm** configuration, edit **config/doctrine.yaml**: - -```yaml -doctrine: - dbal: - # your dbal config here - - orm: - auto_generate_proxy_classes: '%kernel.debug%' - auto_mapping: true - # only these lines are added additionally - mappings: - translatable: - type: attribute # or annotation or xml - alias: Gedmo - prefix: Gedmo\Translatable\Entity - # make sure vendor library location is correct - dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/src/Translatable/Entity" -``` - -After that, running **php bin/console doctrine:mapping:info** you should see the output: - -``` -Found 3 entities mapped in entity manager default: -[OK] Gedmo\Translatable\Entity\MappedSuperclass\AbstractPersonalTranslation -[OK] Gedmo\Translatable\Entity\MappedSuperclass\AbstractTranslation -[OK] Gedmo\Translatable\Entity\Translation +```sh +composer require doctrine/mongodb-odm doctrine/mongodb-odm-bundle gedmo/doctrine-extensions ``` -Well, we mapped only **translatable** for now, it really depends on your needs, which extensions -your application uses. -**Note:** there is **Gedmo\Translatable\Entity\Translation** which is not a super class, in that case -if you create a doctrine schema, it will add **ext_translations** table, which might not be useful -to you also. To skip mapping of these entities, you can map **only superclasses** +For Doctrine ORM users, this Composer command will install all required dependencies: -```yaml -mappings: - translatable: - type: attribute # or annotation or xml - alias: Gedmo - prefix: Gedmo\Translatable\Entity - # make sure vendor library location is correct - dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/src/Translatable/Entity/MappedSuperclass" +```sh +composer require doctrine/dbal doctrine/doctrine-bundle doctrine/orm gedmo/doctrine-extensions ``` -The configuration above, adds a **/MappedSuperclass** into directory depth, after running -**php bin/console doctrine:mapping:info** you should only see now: +## Registering Extension Listeners -``` -Found 2 entities mapped in entity manager default: -[OK] Gedmo\Translatable\Entity\MappedSuperclass\AbstractPersonalTranslation -[OK] Gedmo\Translatable\Entity\MappedSuperclass\AbstractTranslation -``` +At the heart of the Doctrine Extensions library are the listeners which enable each extension. The below example demonstrates +how to register and enable all listeners provided by this library. -This is very useful for advanced requirements and quite simple to understand. So now let's map -everything the extensions provide: +### Extensions Compatible with all Managers -```yaml -# only orm config branch of doctrine -orm: - auto_generate_proxy_classes: '%kernel.debug%' - auto_mapping: true - # only these lines are added additionally - mappings: - translatable: - type: attribute # or annotation or xml - alias: Gedmo - prefix: Gedmo\Translatable\Entity - # make sure vendor library location is correct - dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/src/Translatable/Entity" - loggable: - type: attribute # or annotation or xml - alias: Gedmo - prefix: Gedmo\Loggable\Entity - dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/src/Loggable/Entity" - tree: - type: attribute # or annotation or xml - alias: Gedmo - prefix: Gedmo\Tree\Entity - dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/src/Tree/Entity" -``` - -## Filters +> [!NOTE] +> This example shows the configuration when using the ORM and `DoctrineBundle` with a single default entity manager. When using the MongoDB ODM and `DoctrineMongoDBBundle`, the tag name should be `doctrine_mongodb.odm.event_listener` instead of `doctrine.event_listener`. When using an application with multiple managers, a separate tag is needed with the `connection` attribute for each connection. -The **softdeleteable** ORM filter also needs to be configured, so that soft deleted records are filtered when querying. -To do so, add this filter info to your **doctrine.orm** configuration, edit **config/doctrine.yaml**: ```yaml -doctrine: - dbal: - # your dbal config here - orm: - auto_generate_proxy_classes: '%kernel.debug%' - auto_mapping: true - # only these lines are added additionally - filters: - softdeleteable: - class: Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter -``` - - -## Doctrine extension listener services - -Next, the heart of extensions are behavioral listeners which pours all the sugar. We will -create a **yaml** service file in our config directory. The setup can be different, your config could be located -in the bundle, it depends on your preferences. Edit **config/packages/doctrine_extensions.yaml** - -```yaml -# services to handle doctrine extensions -# import it in config/packages/doctrine_extensions.yaml services: # Attribute mapping driver for the Doctrine Extension listeners gedmo.mapping.driver.attribute: class: Gedmo\Mapping\Driver\AttributeReader - # Doctrine Extension listeners to handle behaviors - gedmo.listener.tree: - class: Gedmo\Tree\TreeListener + # Gedmo Blameable Extension Listener + gedmo.listener.blameable: + class: Gedmo\Blameable\BlameableListener tags: - - { name: doctrine.event_listener, event: 'prePersist'} - - { name: doctrine.event_listener, event: 'preUpdate'} - - { name: doctrine.event_listener, event: 'preRemove'} - - { name: doctrine.event_listener, event: 'onFlush'} - - { name: doctrine.event_listener, event: 'loadClassMetadata'} - - { name: doctrine.event_listener, event: 'postPersist'} - - { name: doctrine.event_listener, event: 'postUpdate'} - - { name: doctrine.event_listener, event: 'postRemove'} + - { name: doctrine.event_listener, event: 'prePersist' } + - { name: doctrine.event_listener, event: 'onFlush' } + - { name: doctrine.event_listener, event: 'loadClassMetadata' } calls: # Uncomment the below call if using attributes, and comment the call for the annotation reader - # - [ setAnnotationReader, [ "@gedmo.mapping.driver.attribute" ] ] + # - [ setAnnotationReader, [ '@gedmo.mapping.driver.attribute' ] ] # The `annotation_reader` service was deprecated in Symfony 6.4 and removed in Symfony 7.0 - - [ setAnnotationReader, [ "@annotation_reader" ] ] + - [ setAnnotationReader, [ '@annotation_reader' ] ] - Gedmo\Translatable\TranslatableListener: + # Gedmo IP Traceable Extension Listener + gedmo.listener.ip_traceable: + class: Gedmo\IpTraceable\IpTraceableListener tags: - - { name: doctrine.event_listener, event: 'postLoad' } - - { name: doctrine.event_listener, event: 'postPersist' } - - { name: doctrine.event_listener, event: 'preFlush' } + - { name: doctrine.event_listener, event: 'prePersist' } - { name: doctrine.event_listener, event: 'onFlush' } - { name: doctrine.event_listener, event: 'loadClassMetadata' } calls: # Uncomment the below call if using attributes, and comment the call for the annotation reader - # - [ setAnnotationReader, [ "@gedmo.mapping.driver.attribute" ] ] + # - [ setAnnotationReader, [ '@gedmo.mapping.driver.attribute' ] ] # The `annotation_reader` service was deprecated in Symfony 6.4 and removed in Symfony 7.0 - - [ setAnnotationReader, [ "@annotation_reader" ] ] - - - [ setDefaultLocale, [ "%locale%" ] ] - - [ setTranslationFallback, [ false ] ] + - [ setAnnotationReader, [ '@annotation_reader' ] ] - gedmo.listener.timestampable: - class: Gedmo\Timestampable\TimestampableListener + # Gedmo Loggable Extension Listener + gedmo.listener.loggable: + class: Gedmo\Loggable\LoggableListener tags: - - { name: doctrine.event_listener, event: 'prePersist' } - { name: doctrine.event_listener, event: 'onFlush' } - { name: doctrine.event_listener, event: 'loadClassMetadata' } + - { name: doctrine.event_listener, event: 'postPersist' } calls: # Uncomment the below call if using attributes, and comment the call for the annotation reader - # - [ setAnnotationReader, [ "@gedmo.mapping.driver.attribute" ] ] + # - [ setAnnotationReader, [ '@gedmo.mapping.driver.attribute' ] ] # The `annotation_reader` service was deprecated in Symfony 6.4 and removed in Symfony 7.0 - - [ setAnnotationReader, [ "@annotation_reader" ] ] + - [ setAnnotationReader, [ '@annotation_reader' ] ] + # Gedmo Sluggable Extension Listener gedmo.listener.sluggable: class: Gedmo\Sluggable\SluggableListener tags: - - { name: doctrine.event_listener, event: 'prePersist' } - { name: doctrine.event_listener, event: 'onFlush' } - { name: doctrine.event_listener, event: 'loadClassMetadata' } + - { name: doctrine.event_listener, event: 'prePersist' } + calls: + # Uncomment the below call if using attributes, and comment the call for the annotation reader + # - [ setAnnotationReader, [ '@gedmo.mapping.driver.attribute' ] ] + # The `annotation_reader` service was deprecated in Symfony 6.4 and removed in Symfony 7.0 + - [ setAnnotationReader, [ '@annotation_reader' ] ] + + # Gedmo Soft Deleteable Extension listener + gedmo.listener.soft_deleteable: + class: Gedmo\SoftDeleteable\SoftDeleteableListener + tags: + - { name: doctrine.event_listener, event: 'loadClassMetadata' } + - { name: doctrine.event_listener, event: 'onFlush' } calls: # Uncomment the below call if using attributes, and comment the call for the annotation reader - # - [ setAnnotationReader, [ "@gedmo.mapping.driver.attribute" ] ] + # - [ setAnnotationReader, [ '@gedmo.mapping.driver.attribute' ] ] # The `annotation_reader` service was deprecated in Symfony 6.4 and removed in Symfony 7.0 - - [ setAnnotationReader, [ "@annotation_reader" ] ] + - [ setAnnotationReader, [ '@annotation_reader' ] ] + # The `clock` service was introduced in Symfony 6.2; if using an older Symfony version, you can either comment this call or provide your own PSR-20 Clock implementation + - [ setClock, [ '@clock' ] ] + # Gedmo Sortable Extension listener gedmo.listener.sortable: class: Gedmo\Sortable\SortableListener tags: @@ -225,338 +125,357 @@ services: - { name: doctrine.event_listener, event: 'postFlush' } calls: # Uncomment the below call if using attributes, and comment the call for the annotation reader - # - [ setAnnotationReader, [ "@gedmo.mapping.driver.attribute" ] ] + # - [ setAnnotationReader, [ '@gedmo.mapping.driver.attribute' ] ] # The `annotation_reader` service was deprecated in Symfony 6.4 and removed in Symfony 7.0 - - [ setAnnotationReader, [ "@annotation_reader" ] ] + - [ setAnnotationReader, [ '@annotation_reader' ] ] - gedmo.listener.softdeleteable: - class: Gedmo\SoftDeleteable\SoftDeleteableListener + # Gedmo Timestampable Extension Listener + gedmo.listener.timestampable: + class: Gedmo\Timestampable\TimestampableListener tags: + - { name: doctrine.event_listener, event: 'prePersist' } - { name: doctrine.event_listener, event: 'onFlush' } - { name: doctrine.event_listener, event: 'loadClassMetadata' } calls: # Uncomment the below call if using attributes, and comment the call for the annotation reader - # - [ setAnnotationReader, [ "@gedmo.mapping.driver.attribute" ] ] + # - [ setAnnotationReader, [ '@gedmo.mapping.driver.attribute' ] ] # The `annotation_reader` service was deprecated in Symfony 6.4 and removed in Symfony 7.0 - - [ setAnnotationReader, [ "@annotation_reader" ] ] - - Gedmo\Loggable\LoggableListener: + - [ setAnnotationReader, [ '@annotation_reader' ] ] + # The `clock` service was introduced in Symfony 6.2; if using an older Symfony version, you can either comment this call or provide your own PSR-20 Clock implementation + - [ setClock, [ '@clock' ] ] + + # Gedmo Translatable Extension Listener + gedmo.listener.translatable: + class: Gedmo\Translatable\TranslatableListener tags: + - { name: doctrine.event_listener, event: 'postLoad' } + - { name: doctrine.event_listener, event: 'postPersist' } + - { name: doctrine.event_listener, event: 'preFlush' } - { name: doctrine.event_listener, event: 'onFlush' } - { name: doctrine.event_listener, event: 'loadClassMetadata' } - - { name: doctrine.event_listener, event: 'postPersist' } calls: # Uncomment the below call if using attributes, and comment the call for the annotation reader - # - [ setAnnotationReader, [ "@gedmo.mapping.driver.attribute" ] ] + # - [ setAnnotationReader, [ '@gedmo.mapping.driver.attribute' ] ] # The `annotation_reader` service was deprecated in Symfony 6.4 and removed in Symfony 7.0 - - [ setAnnotationReader, [ "@annotation_reader" ] ] + - [ setAnnotationReader, [ '@annotation_reader' ] ] + # The Kernel's `locale` parameter is used to configure the default locale for the extension + - [ setDefaultLocale, [ '%locale%' ] ] - Gedmo\Blameable\BlameableListener: + # Gedmo Tree Extension Listener + gedmo.listener.tree: + class: Gedmo\Tree\TreeListener tags: - - { name: doctrine.event_listener, event: 'prePersist' } - - { name: doctrine.event_listener, event: 'onFlush' } - - { name: doctrine.event_listener, event: 'loadClassMetadata' } + - { name: doctrine.event_listener, event: 'prePersist'} + - { name: doctrine.event_listener, event: 'preUpdate'} + - { name: doctrine.event_listener, event: 'preRemove'} + - { name: doctrine.event_listener, event: 'onFlush'} + - { name: doctrine.event_listener, event: 'loadClassMetadata'} + - { name: doctrine.event_listener, event: 'postPersist'} + - { name: doctrine.event_listener, event: 'postUpdate'} + - { name: doctrine.event_listener, event: 'postRemove'} calls: # Uncomment the below call if using attributes, and comment the call for the annotation reader - # - [ setAnnotationReader, [ "@gedmo.mapping.driver.attribute" ] ] + # - [ setAnnotationReader, [ '@gedmo.mapping.driver.attribute' ] ] # The `annotation_reader` service was deprecated in Symfony 6.4 and removed in Symfony 7.0 - - [ setAnnotationReader, [ "@annotation_reader" ] ] - - Gedmo\IpTraceable\IpTraceableListener: + - [ setAnnotationReader, [ '@annotation_reader' ] ] +``` + +### Extensions Compatible with MongoDB ODM Only + +> [!NOTE] +> This example shows the configuration when using the MongoDB ODM and `DoctrineMongoDBBundle` with a single default document manager. When using an application with multiple managers, a separate tag is needed with the `connection` attribute for each connection. + +```yaml +services: + # Gedmo Reference Integrity Extension Listener + gedmo.listener.reference_integrity: + class: Gedmo\ReferenceIntegrity\ReferenceIntegrityListener tags: - - { name: doctrine.event_listener, event: 'prePersist' } - - { name: doctrine.event_listener, event: 'onFlush' } - - { name: doctrine.event_listener, event: 'loadClassMetadata' } + - { name: doctrine_mongodb.odm.event_listener, event: 'loadClassMetadata' } + - { name: doctrine_mongodb.odm.event_listener, event: 'preRemove' } calls: # Uncomment the below call if using attributes, and comment the call for the annotation reader - # - [ setAnnotationReader, [ "@gedmo.mapping.driver.attribute" ] ] + # - [ setAnnotationReader, [ '@gedmo.mapping.driver.attribute' ] ] # The `annotation_reader` service was deprecated in Symfony 6.4 and removed in Symfony 7.0 - - [ setAnnotationReader, [ "@annotation_reader" ] ] + - [ setAnnotationReader, [ '@annotation_reader' ] ] + # Gedmo References Extension Listener + gedmo.listener.references: + class: Gedmo\References\ReferencesListener + tags: + - { name: doctrine_mongodb.odm.event_listener, event: 'postLoad' } + - { name: doctrine_mongodb.odm.event_listener, event: 'loadClassMetadata' } + - { name: doctrine_mongodb.odm.event_listener, event: 'prePersist' } + - { name: doctrine_mongodb.odm.event_listener, event: 'preUpdate' } + calls: + # Uncomment the below call if using attributes, and comment the call for the annotation reader + # - [ setAnnotationReader, [ '@gedmo.mapping.driver.attribute' ] ] + # The `annotation_reader` service was deprecated in Symfony 6.4 and removed in Symfony 7.0 + - [ setAnnotationReader, [ '@annotation_reader' ] ] ``` -So what does it include in general? Well, it creates services for all extension listeners. -You can remove some which you do not use, or change them as you need. **Translatable** for instance, -sets the default locale to the value of your `%locale%` parameter, you can configure it differently. - -**Note:** In case you noticed, there is **EventSubscriber\DoctrineExtensionSubscriber**. -You will need to create this subscriber class if you use **loggable** , **translatable** or **blameable** -behaviors. This listener will set the **locale used** from request and **username** to -loggable and blameable. So, to finish the setup create **EventSubscriber\DoctrineExtensionSubscriber** - -## Register event listener for [Symfony Doctrine MongoDB Bundle](https://github.com/doctrine/DoctrineMongoDBBundle) +### Extensions Compatible with ORM Only -You also need to manually tag the listeners. Otherwise, the listeners will not be listening to the triggered events -of Doctrine. +> [!NOTE] +> This example shows the configuration when using the ORM and `DoctrineBundle` with a single default entity manager. When using an application with multiple managers, a separate tag is needed with the `connection` attribute for each connection. ```yaml services: - Gedmo\Loggable\LoggableListener: + # Gedmo Uploadable Extension Listener + gedmo.listener.uploadable: + class: Gedmo\Uploadable\UploadableListener tags: - - { name: doctrine_mongodb.odm.event_listener, event: 'onFlush' } - - { name: doctrine_mongodb.odm.event_listener, event: 'loadClassMetadata' } - - { name: doctrine_mongodb.odm.event_listener, event: 'postPersist' } + - { name: doctrine.event_listener, event: 'loadClassMetadata'} + - { name: doctrine.event_listener, event: 'preFlush'} + - { name: doctrine.event_listener, event: 'onFlush'} + - { name: doctrine.event_listener, event: 'postFlush'} calls: # Uncomment the below call if using attributes, and comment the call for the annotation reader - # - [ setAnnotationReader, [ "@gedmo.mapping.driver.attribute" ] ] + # - [ setAnnotationReader, [ '@gedmo.mapping.driver.attribute' ] ] # The `annotation_reader` service was deprecated in Symfony 6.4 and removed in Symfony 7.0 - - [ setAnnotationReader, [ "@annotation_reader" ] ] + - [ setAnnotationReader, [ '@annotation_reader' ] ] ``` -```php - [!NOTE] +> These extensions only provide mappings through annotations or attributes; if using annotations, you will need to ensure the deprecated [`doctrine/annotations`](https://www.doctrine-project.org/projects/annotations.html) library is installed and enabled. -final class DoctrineExtensionSubscriber implements EventSubscriberInterface -{ - private BlameableListener $blameableListener; +### MongoDB ODM Mapping + +> [!IMPORTANT] +> The tree extension does NOT have any objects to map when using the MongoDB ODM. - private TokenStorageInterface $tokenStorage; +The below example shows a configuration adding all available mappings to the default document manager. - private TranslatableListener $translatableListener; +```yaml +doctrine_mongodb: + document_managers: + default: + mappings: + loggable: + type: attribute # or annotation + alias: GedmoLoggable + prefix: Gedmo\Loggable\Document + dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/src/Loggable/Document" + is_bundle: false + translatable: + type: attribute # or annotation + alias: GedmoTranslatable + prefix: Gedmo\Translatable\Document + dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/src/Translatable/Document" + is_bundle: false +``` - private LoggableListener $loggableListener; +To verify your configuration, you can use the `doctrine:mongodb:mapping:info` command to make sure the entities are registered. +```sh +$ bin/console doctrine:mongodb:mapping:info + Found X documents mapped in document manager default: + [OK] Gedmo\Loggable\Document\LogEntry + [OK] Gedmo\Loggable\Document\MappedSuperclass\AbstractLogEntry + [OK] Gedmo\Translatable\Document\MappedSuperclass\AbstractPersonalTranslation + [OK] Gedmo\Translatable\Document\MappedSuperclass\AbstractTranslation + [OK] Gedmo\Translatable\Document\Translation +``` - public function __construct( - BlameableListener $blameableListener, - TokenStorageInterface $tokenStorage, - TranslatableListener $translatableListener, - LoggableListener $loggableListener - ) { - $this->blameableListener = $blameableListener; - $this->tokenStorage = $tokenStorage; - $this->translatableListener = $translatableListener; - $this->loggableListener = $loggableListener; - } +### ORM Mapping +The below example shows a configuration adding all available mappings to the default entity manager. - public static function getSubscribedEvents(): array - { - return [ - KernelEvents::REQUEST => 'onKernelRequest', - KernelEvents::FINISH_REQUEST => 'onLateKernelRequest' - ]; - } - public function onKernelRequest(): void - { - if ( - $this->tokenStorage->getToken() !== null && - $this->tokenStorage->getToken()->getUser() !== null - ) { - $this->blameableListener->setUserValue($this->tokenStorage->getToken()->getUser()); - } - } +```yaml +doctrine: + orm: + default: + mappings: + loggable: + type: attribute # or annotation + alias: GedmoLoggable + prefix: Gedmo\Loggable\Entity + dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/src/Loggable/Entity" + is_bundle: false + translatable: + type: attribute # or annotation + alias: GedmoTranslatable + prefix: Gedmo\Translatable\Entity + dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/src/Translatable/Entity" + is_bundle: false + tree: + type: attribute # or annotation + alias: GedmoTree + prefix: Gedmo\Tree\Entity + dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/src/Tree/Entity" + is_bundle: false +``` - public function onLateKernelRequest(FinishRequestEvent $event): void - { - $this->translatableListener->setTranslatableLocale($event->getRequest()->getLocale()); - } -} +To verify your configuration, you can use the `doctrine:mapping:info` command to make sure the entities are registered. + +```sh +$ bin/console doctrine:mapping:info + Found X mapped entities: + [OK] Gedmo\Loggable\Entity\LogEntry + [OK] Gedmo\Loggable\Entity\MappedSuperclass\AbstractLogEntry + [OK] Gedmo\Translatable\Entity\MappedSuperclass\AbstractPersonalTranslation + [OK] Gedmo\Translatable\Entity\MappedSuperclass\AbstractTranslation + [OK] Gedmo\Translatable\Entity\Translation + [OK] Gedmo\Tree\Entity\MappedSuperclass\AbstractClosure ``` - +## Registering Filters -## Example +### Soft Deleteable Filter -After that, you have your extensions set up and ready to be used! Too easy right? Well, -if you do not believe me, let's create a simple entity in our project: +When using the [Soft Deleteable](../softdeleteable.md) extension, a filter is available which allows configuring whether +soft-deleted objects are included in query results. -```php +> [!NOTE] +> The Symfony bundles default filters to not being enabled, these examples will enable the filters by default. -id; - } +When using the [Blameable](../blameable.md), [IP Traceable](../ip_traceable.md), [Loggable](../loggable.md), or +[Translatable](../translatable.md) extensions, to work correctly, they require extra information that must be set +at runtime, typically during the `kernel.request` event. The below example is an event subscriber class which configures +all of these extensions. - public function setTitle(?string $title): void - { - $this->title = $title; - } +```php +title; - } +use Gedmo\Blameable\BlameableListener; +use Gedmo\IpTraceable\IpTraceableListener; +use Gedmo\Loggable\LoggableListener; +use Gedmo\Translatable\TranslatableListener; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\Event\RequestEvent; +use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; +use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; - public function getCreated(): ?DateTimeImmutable - { - return $this->created; - } +final class GedmoExtensionsEventSubscriber implements EventSubscriberInterface +{ + public function __construct( + private BlameableListener $blameableListener, + private IpTraceableListener $ipTraceableListener, + private LoggableListener $loggableListener, + private TranslatableListener $translatableListener, + private ?AuthorizationCheckerInterface $authorizationChecker = null, + private ?TokenStorageInterface $tokenStorage = null, + ) {} - public function getUpdated(): ?DateTimeImmutable + public static function getSubscribedEvents(): array { - return $this->updated; + return [ + KernelEvents::REQUEST => [ + ['configureBlameableListener'], // Must run after the user is authenticated + ['configureIpTraceableListener', 512], // Runs early since this only requires the Request object + ['configureLoggableListener'], // Must run after the user is authenticated + ['configureTranslatableListener'], // Must run after the locale is configured + ], + ]; } - public function getDeletedAt(): ?DateTimeImmutable - { - return $this->deletedAt; - } - - public function setDeletedAt(?DateTimeImmutable $deletedAt): void + /** + * Configures the blameable listener using the currently authenticated user + */ + public function configureBlameableListener(RequestEvent $event): void { - $this->deletedAt = $deletedAt; - } -} -``` - -Now, let's have some fun: - -- if you have not created the database yet, run `php bin/console doctrine:database:create` -- create the schema `php bin/console doctrine:schema:create` + // Only applies to the main request + if (!$event->isMainRequest()) { + return; + } -Everything will work just fine, you can modify the **App\Controller\DemoController** -and add an action to test how it works: + // If the required security component services weren't provided, there's nothing we can do + if (null === $this->authorizationChecker || null === $this->tokenStorage) { + return; + } -```php -// file: src/Controller/DemoController.php -// include this code portion + $token = $this->tokenStorage->getToken(); -/** - * @Route("/posts", name="_demo_posts") - */ -public function postsAction(EntityManagerInterface $em): Response -{ - $repository = $em->getRepository(App\Entity\BlogPost::class); - // create some posts in case if there aren't any - if (!$repository->find('hello_world')) { - $post = new App\Entity\BlogPost(); - $post->setTitle('Hello world'); - - $next = new App\Entity\BlogPost(); - $next->setTitle('Doctrine extensions'); - - $em->persist($post); - $em->persist($next); - $em->flush(); + // Only set the user information if there is a token in storage and it represents an authenticated user + if (null !== $token && $this->authorizationChecker->isGranted('IS_AUTHENTICATED')) { + $this->blameableListener->setUserValue($token->getUser()); + } } - $posts = $repository->findAll(); - dd($posts); -} -``` - -Now if you follow the url: **http://your_virtual_host/demo/posts** you -should see a print of posts, this is only an extension demo, we will not create a template. - + /** + * Configures the IP traceable listener using the current request + */ + public function configureIpTraceableListener(RequestEvent $event): void + { + // Only applies to the main request + if (!$event->isMainRequest()) { + return; + } -## More tips + $ip = $event->getRequest()->getClientIp(); -Regarding, the setup, I do not think it's too complicated to use, in general it is simple -enough, and lets you understand at least small parts on how you can hook mappings into doctrine, and -how easily extension services are added. This configuration does not hide anything behind -curtains and allows you to modify the configuration as you require. + // Only set the IP address if available + if (null !== $ip) { + $this->ipTraceableListener->setIpValue($ip); + } + } -### Multiple entity managers + /** + * Configures the loggable listener using the currently authenticated user + */ + public function configureLoggableListener(RequestEvent $event): void + { + // Only applies to the main request + if (!$event->isMainRequest()) { + return; + } -If you use more than one entity manager, you can simply tag the subscriber -with other the manager name: + // If the required security component services weren't provided, there's nothing we can do + if (null === $this->authorizationChecker || null === $this->tokenStorage) { + return; + } + $token = $this->tokenStorage->getToken(); -Regarding, mapping of ODM mongodb, it's basically the same: + // Only set the user information if there is a token in storage and it represents an authenticated user + if (null !== $token && $this->authorizationChecker->isGranted('IS_AUTHENTICATED')) { + $this->loggableListener->setUsername($token->getUser()); + } + } -```yaml -doctrine_mongodb: - default_database: 'my_database' - default_connection: 'default' - default_document_manager: 'default' - connections: - default: ~ - document_managers: - default: - connection: 'default' - auto_mapping: true - mappings: - translatable: - type: attribute # or annotation or xml - alias: GedmoDocument - prefix: Gedmo\Translatable\Document - # make sure vendor library location is correct - dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/src/Translatable/Document" + /** + * Configures the translatable listener using the request locale + */ + public function configureTranslatableListener(RequestEvent $event): void + { + $this->translatableListener->setTranslatableLocale($event->getRequest()->getLocale()); + } +} ``` - -This also shows, how to make mappings based on single manager. All what differs is that **Document** -instead of **Entity** is used. I haven't tested it with mongo though. - -**Note:** [extension repository](https://github.com/doctrine-extensions/DoctrineExtensions) contains all -[documentation](../doc) you may need -to understand how you can use it in your projects. - - - -## Alternative over configuration - -You can use [StofDoctrineExtensionsBundle](https://github.com/stof/StofDoctrineExtensionsBundle) which is a wrapper of these extensions - -## Troubleshooting - -- Make sure there are no *.orm.yml or *.orm.xml files for your Entities in your bundles Resources/config/doctrine directory. With those files in place the annotations won't be taken into account. From ce10750dfb13ae9cf180b00e36cd579808b7fbc4 Mon Sep 17 00:00:00 2001 From: Michael Babker Date: Sun, 30 Jun 2024 18:11:14 -0400 Subject: [PATCH 3/6] Rewrite the Laminas integration guide --- doc/frameworks/laminas.md | 436 ++++++++++++++++++++++++++++++++------ 1 file changed, 366 insertions(+), 70 deletions(-) diff --git a/doc/frameworks/laminas.md b/doc/frameworks/laminas.md index 5f68eb25b6..c957da476d 100644 --- a/doc/frameworks/laminas.md +++ b/doc/frameworks/laminas.md @@ -1,85 +1,381 @@ -## Using Gedmo Doctrine Extensions in Laminas +# Integrate the Doctrine Extensions in Laminas -Assuming you are familiar with [DoctrineModule](https://github.com/doctrine/DoctrineModule) (if not, you should definitely start there!), integrating Doctrine Extensions with Laminas application is super-easy. +This guide will demonstrate how to integrate the Doctrine Extensions library into a Laminas application. -### Composer +## Index -Add `doctrine/doctrine-module`, `doctrine/doctrine-orm-module` or `doctrine/doctrine-mongo-odm-module` to composer.json file +- [Getting Started](#getting-started) +- [Registering Extension Listeners](#registering-extension-listeners) +- [Registering Mapping Configuration](#registering-mapping-configuration) +- [Registering Filters](#registering-filters) +- [Configuring Extensions via Event Listeners](#configuring-extensions-via-event-listeners) -Then run `composer.phar update`. +## Getting Started -### Configuration +> [!TIP] +> This guide is written using the Laminas MVC quick start as the foundation. -Once libraries are installed, you can tell Doctrine which behaviors you want to use, by declaring appropriate subscribers in Event Manager settings. Together with [entity mapping options](https://github.com/doctrine/DoctrineORMModule#entities-settings), your module configuration file should look like following: +Assuming you have already [created your Laminas application](https://docs.laminas.dev/laminas-mvc/quick-start/), +the next step will be to ensure you've installed this library and the Doctrine libraries you will need. + +For Doctrine MongoDB ODM users, this Composer command will install all required dependencies: + +```sh +composer require doctrine/doctrine-module doctrine/doctrine-mongo-odm-module doctrine/mongodb-odm gedmo/doctrine-extensions +``` + +For Doctrine ORM users, this Composer command will install all required dependencies: + +```sh +composer require doctrine/dbal doctrine/doctrine-module doctrine/doctrine-orm-module doctrine/orm gedmo/doctrine-extensions +``` + +## Registering Extension Listeners + +At the heart of the Doctrine Extensions library are the listeners which enable each extension. The below example demonstrates +how to register and enable all listeners provided by this library. + +### Extensions Compatible with all Managers + +```php + [ + 'invokables' => [ + 'gedmo.mapping.driver.attribute' => AttributeReader::class, + ], + 'factories' => [ + 'gedmo.listener.blameable' => function (ContainerInterface $container, string $requestedName): BlameableListener { + $listener = new BlameableListener(); + + // This call configures the listener to use the attribute driver service created above; if using annotations, you will need to provide the appropriate service instead + $listener->setAnnotationReader($container->get('gedmo.mapping.driver.attribute')); + + return $listener; + }, + 'gedmo.listener.ip_traceable' => function (ContainerInterface $container, string $requestedName): IpTraceableListener { + $listener = new IpTraceableListener(); + + // This call configures the listener to use the attribute driver service created above; if using annotations, you will need to provide the appropriate service instead + $listener->setAnnotationReader($container->get('gedmo.mapping.driver.attribute')); + + return $listener; + }, + 'gedmo.listener.loggable' => function (ContainerInterface $container, string $requestedName): LoggableListener { + $listener = new LoggableListener(); + + // This call configures the listener to use the attribute driver service created above; if using annotations, you will need to provide the appropriate service instead + $listener->setAnnotationReader($container->get('gedmo.mapping.driver.attribute')); + + return $listener; + }, + 'gedmo.listener.sluggable' => function (ContainerInterface $container, string $requestedName): SluggableListener { + $listener = new SluggableListener(); + + // This call configures the listener to use the attribute driver service created above; if using annotations, you will need to provide the appropriate service instead + $listener->setAnnotationReader($container->get('gedmo.mapping.driver.attribute')); + + return $listener; + }, + 'gedmo.listener.soft_deleteable' => function (ContainerInterface $container, string $requestedName): SoftDeleteableListener { + $listener = new SoftDeleteableListener(); + + // This call configures the listener to use the attribute driver service created above; if using annotations, you will need to provide the appropriate service instead + $listener->setAnnotationReader($container->get('gedmo.mapping.driver.attribute')); + + // If your application uses a PSR-20 clock, you can provide it to this listener by uncommenting the below line + // $listener->setClock($container->get(ClockInterface::class)); + + return $listener; + }, + 'gedmo.listener.sortable' => function (ContainerInterface $container, string $requestedName): SortableListener { + $listener = new SortableListener(); + + // This call configures the listener to use the attribute driver service created above; if using annotations, you will need to provide the appropriate service instead + $listener->setAnnotationReader($container->get('gedmo.mapping.driver.attribute')); + + return $listener; + }, + 'gedmo.listener.timestampable' => function (ContainerInterface $container, string $requestedName): TimestampableListener { + $listener = new TimestampableListener(); + + // This call configures the listener to use the attribute driver service created above; if using annotations, you will need to provide the appropriate service instead + $listener->setAnnotationReader($container->get('gedmo.mapping.driver.attribute')); + + // If your application uses a PSR-20 clock, you can provide it to this listener by uncommenting the below line + // $listener->setClock($container->get(ClockInterface::class)); + + return $listener; + }, + 'gedmo.listener.translatable' => function (ContainerInterface $container, string $requestedName): TranslatableListener { + $listener = new TranslatableListener(); + + // This call configures the listener to use the attribute driver service created above; if using annotations, you will need to provide the appropriate service instead + $listener->setAnnotationReader($container->get('gedmo.mapping.driver.attribute')); + + // If your application uses a PSR-20 clock, you can provide it to this listener by uncommenting the below line + // $listener->setClock($container->get(ClockInterface::class)); + + return $listener; + }, + ], + ], + 'doctrine' => [ + 'eventmanager' => [ + 'orm_default' => [ + 'subscribers' => [ + 'gedmo.listener.blameable', + 'gedmo.listener.ip_traceable', + 'gedmo.listener.loggable', + 'gedmo.listener.sluggable', + 'gedmo.listener.soft_deleteable', + 'gedmo.listener.sortable', + 'gedmo.listener.timestampable', + 'gedmo.listener.translatable', + 'gedmo.listener.tree', + ], + ], + ], + ], +]; +``` + +### Extensions Compatible with MongoDB ODM Only + +```php + [ + 'factories' => [ + 'gedmo.listener.reference_integrity' => function (ContainerInterface $container, string $requestedName): ReferenceIntegrityListener { + $listener = new ReferenceIntegrityListener(); + + // This call configures the listener to use the attribute driver service created above; if using annotations, you will need to provide the appropriate service instead + $listener->setAnnotationReader($container->get('gedmo.mapping.driver.attribute')); + + return $listener; + }, + 'gedmo.listener.references' => function (ContainerInterface $container, string $requestedName): ReferencesListener { + $listener = new ReferencesListener(); + + // This call configures the listener to use the attribute driver service created above; if using annotations, you will need to provide the appropriate service instead + $listener->setAnnotationReader($container->get('gedmo.mapping.driver.attribute')); + + return $listener; + }, + ], + ], + 'doctrine' => [ + 'eventmanager' => [ + 'odm_default' => [ + 'subscribers' => [ + 'gedmo.listener.reference_integrity', + 'gedmo.listener.references', + ], + ], + ], + ], +]; +``` + +### Extensions Compatible with ORM Only ```php -return array( - 'doctrine' => array( - 'eventmanager' => array( - 'orm_default' => array( - 'subscribers' => array( - - // pick any listeners you need - 'Gedmo\Tree\TreeListener', - 'Gedmo\Timestampable\TimestampableListener', - 'Gedmo\Sluggable\SluggableListener', - 'Gedmo\Loggable\LoggableListener', - 'Gedmo\Sortable\SortableListener' - ), - ), - ), - 'driver' => array( - 'my_driver' => array( - 'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver', - 'cache' => 'array', - 'paths' => array(__DIR__ . '/../src/MyModule/Entity') - ), - 'orm_default' => array( - 'drivers' => array( - 'MyModule\Entity' => 'my_driver' - ), - ), - ), - ), -); + [ + 'factories' => [ + 'gedmo.listener.uploadable' => function (ContainerInterface $container, string $requestedName): UploadableListener { + $listener = new UploadableListener(); + + // This call configures the listener to use the attribute driver service created above; if using annotations, you will need to provide the appropriate service instead + $listener->setAnnotationReader($container->get('gedmo.mapping.driver.attribute')); + + return $listener; + }, + ], + ], + 'doctrine' => [ + 'eventmanager' => [ + 'orm_default' => [ + 'subscribers' => [ + 'gedmo.listener.uploadable', + ], + ], + ], + ], +]; ``` -That's it! From now on you can use Gedmo annotations, just as it is described in [documentation](../annotations.md). +## Registering Mapping Configuration + +When using the [Loggable](../loggable.md), [Translatable](../translatable.md), or [Tree](../tree.md) extensions, you will +need to register the mappings for these extensions to your object managers. + +> [!NOTE] +> These extensions only provide mappings through annotations or attributes; if using annotations, you will need to ensure the deprecated [`doctrine/annotations`](https://www.doctrine-project.org/projects/annotations.html) library is installed and configured. + +### MongoDB ODM Mapping + +> [!IMPORTANT] +> The tree extension does NOT have any objects to map when using the MongoDB ODM. + +The below example shows a configuration adding all available mappings to the default document manager. + +```php + [ + 'driver' => [ + 'gedmo.odm_driver' => [ + 'class' => AttributeDriver::class, // If your application is using annotations, use the AnnotationDriver class instead + 'paths' => [ + '/path/to/vendor/gedmo/doctrine-extensions/src/Loggable/Document', + '/path/to/vendor/gedmo/doctrine-extensions/src/Translatable/Document', + ], + ], + 'odm_default' => [ + 'drivers' => [ + 'gedmo.odm_driver', // Adds the mapping driver created above to the default mapping chain + ], + ], + ], + ], +]; +``` -#### Note: You may need to provide additional settings for some of the available listeners. +### ORM Mapping -For instance, `Translatable` requires additional metadata driver in order to manage translation tables: +The below example shows a configuration adding all available mappings to the default entity manager. ```php -return array( - 'doctrine' => array( - 'eventmanager' => array( - 'orm_default' => array( - 'subscribers' => array( - 'Gedmo\Translatable\TranslatableListener', - ), - ), - ), - 'driver' => array( - 'my_driver' => array( - 'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver', - 'cache' => 'array', - 'paths' => array(__DIR__ . '/../src/MyModule/Entity') - ), - 'translatable_metadata_driver' => array( - 'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver', - 'cache' => 'array', - 'paths' => array( - 'vendor/gedmo/doctrine-extensions/src/Translatable/Entity', - ), - ), - 'orm_default' => array( - 'drivers' => array( - 'MyModule\Entity' => 'my_driver', - 'Gedmo\Translatable\Entity' => 'translatable_metadata_driver', - ), - ), - ), - ), -); + [ + 'driver' => [ + 'gedmo.orm_driver' => [ + 'class' => AttributeDriver::class, // If your application is using annotations, use the AnnotationDriver class instead + 'paths' => [ + '/path/to/vendor/gedmo/doctrine-extensions/src/Loggable/Entity', + '/path/to/vendor/gedmo/doctrine-extensions/src/Translatable/Entity', + '/path/to/vendor/gedmo/doctrine-extensions/src/Tree/Entity', + ], + ], + 'orm_default' => [ + 'drivers' => [ + 'gedmo.orm_driver', // Adds the mapping driver created above to the default mapping chain + ], + ], + ], + ], +]; ``` + +To verify your configuration, you can use the `orm:info` command from the `doctrine-module` CLI tool to make sure the entities are registered. + +```sh +$ vendor/bin/doctrine-module orm:info + Found X mapped entities: + + [OK] Gedmo\Loggable\Entity\LogEntry + [OK] Gedmo\Loggable\Entity\MappedSuperclass\AbstractLogEntry + [OK] Gedmo\Translatable\Entity\Translation + [OK] Gedmo\Translatable\Entity\MappedSuperclass\AbstractTranslation + [OK] Gedmo\Translatable\Entity\MappedSuperclass\AbstractPersonalTranslation + [OK] Gedmo\Tree\Entity\MappedSuperclass\AbstractClosure +``` + +## Registering Filters + +### Soft Deleteable Filter + +When using the [Soft Deleteable](../softdeleteable.md) extension, a filter is available which allows configuring whether +soft-deleted objects are included in query results. + +> [!NOTE] +> The Laminas modules default filters to not being enabled, you will need to enable them separately. + +#### MongoDB ODM Filter Configuration + +The below example shows a configuration adding the filter to the default document manager. + +```php + [ + 'configuration' => [ + 'odm_default' => [ + 'filters' => [ + 'soft-deleteable' => SoftDeleteableFilter::class, + ], + ], + ], + ], +]; +``` + +#### ORM Filter Configuration + +The below example shows a configuration adding the filter to the default entity manager. + +```php + [ + 'configuration' => [ + 'orm_default' => [ + 'filters' => [ + 'soft-deleteable' => SoftDeleteableFilter::class, + ], + ], + ], + ], +]; +``` + +## Configuring Extensions via Event Listeners + +When using the [Blameable](../blameable.md), [IP Traceable](../ip_traceable.md), [Loggable](../loggable.md), or +[Translatable](../translatable.md) extensions, to work correctly, they require extra information that must be set +at runtime. + +**Help Improve This Documentation** + +Pull requests are welcome to expand this section of the documentation. From 049cd8d9ac6b241959a6288bf5d91259abbbc117 Mon Sep 17 00:00:00 2001 From: Michael Babker Date: Sun, 30 Jun 2024 18:13:54 -0400 Subject: [PATCH 4/6] Add a page covering the Laravel Doctrine integration --- README.md | 2 +- doc/frameworks/laravel.md | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 doc/frameworks/laravel.md diff --git a/README.md b/README.md index d593761f14..74b096b12d 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ flushed in a behavioral way. composer require gedmo/doctrine-extensions * [Symfony](/doc/frameworks/symfony.md) -* [Laravel 5](https://www.laraveldoctrine.org/docs/1.3/extensions) +* [Laravel](/doc/frameworks/laravel.md) * [Laminas](/doc/frameworks/laminas.md) ### Upgrading diff --git a/doc/frameworks/laravel.md b/doc/frameworks/laravel.md new file mode 100644 index 0000000000..0afe9e9834 --- /dev/null +++ b/doc/frameworks/laravel.md @@ -0,0 +1,5 @@ +# Integrate the Doctrine Extensions in Laravel + +When using the Laravel Doctrine package with the Doctrine ORM, you can use the [Laravel Doctrine Extensions](https://www.laraveldoctrine.org/docs/current/extensions) +package to add this library to your application. Please review the extensions package documentation linked earlier for +detailed instructions. From 6024fa018655516c8e8849f697a2c2e27ca2d01b Mon Sep 17 00:00:00 2001 From: Michael Babker Date: Mon, 1 Jul 2024 11:13:01 -0400 Subject: [PATCH 5/6] Misc. updates from review Co-authored-by: Javier Spagnoletti --- doc/frameworks/laminas.md | 12 +++++++----- doc/frameworks/symfony.md | 10 +++++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/doc/frameworks/laminas.md b/doc/frameworks/laminas.md index c957da476d..eebda88cdd 100644 --- a/doc/frameworks/laminas.md +++ b/doc/frameworks/laminas.md @@ -20,13 +20,13 @@ the next step will be to ensure you've installed this library and the Doctrine l For Doctrine MongoDB ODM users, this Composer command will install all required dependencies: -```sh +```shell composer require doctrine/doctrine-module doctrine/doctrine-mongo-odm-module doctrine/mongodb-odm gedmo/doctrine-extensions ``` For Doctrine ORM users, this Composer command will install all required dependencies: -```sh +```shell composer require doctrine/dbal doctrine/doctrine-module doctrine/doctrine-orm-module doctrine/orm gedmo/doctrine-extensions ``` @@ -324,11 +324,12 @@ When using the [Soft Deleteable](../softdeleteable.md) extension, a filter is av soft-deleted objects are included in query results. > [!NOTE] -> The Laminas modules default filters to not being enabled, you will need to enable them separately. +> The default configuration in the Laminas modules does not enable the filters. To use these filters, you will need to enable them separately. #### MongoDB ODM Filter Configuration -The below example shows a configuration adding the filter to the default document manager. +The below example shows a configuration adding the filter to the default document manager. To enable the filter, +you can follow the [Filters documentation guide](https://www.doctrine-project.org/projects/doctrine-mongodb-odm/en/latest/reference/filters.html#disabling-enabling-filters-and-setting-parameters). ```php [!NOTE] -> The Symfony bundles default filters to not being enabled, these examples will enable the filters by default. +> The default configuration in the Symfony bundles does not enable the filters. These examples show how to globally enable them. #### MongoDB ODM Filter Configuration From d80739db1449802e8cf457573061d318ff8c965b Mon Sep 17 00:00:00 2001 From: Michael Babker Date: Mon, 1 Jul 2024 12:11:51 -0400 Subject: [PATCH 6/6] Tweak wording for deprecated annotations support --- doc/annotations.md | 2 +- doc/frameworks/laminas.md | 2 +- doc/frameworks/symfony.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/annotations.md b/doc/annotations.md index 92010c305c..f77ae52d5f 100644 --- a/doc/annotations.md +++ b/doc/annotations.md @@ -1,7 +1,7 @@ # Annotations Reference > [!IMPORTANT] -> To use annotations, you will need the deprecated [`doctrine/annotations`](https://www.doctrine-project.org/projects/annotations.html) library. PHP 8 users are encouraged to migrate and use [attributes](./attributes.md) as annotation support is deprecated in all supported Doctrine object managers. +> Support for annotations is deprecated and will be removed in 4.0. PHP 8 users are encouraged to migrate and use [attributes](./attributes.md) instead of annotations. To use annotations, you will need the [`doctrine/annotations`](https://www.doctrine-project.org/projects/annotations.html) library. Below you will a reference for annotations supported in this extensions library. There will be introduction on usage with examples. For more detailed usage of each diff --git a/doc/frameworks/laminas.md b/doc/frameworks/laminas.md index eebda88cdd..562e6ad280 100644 --- a/doc/frameworks/laminas.md +++ b/doc/frameworks/laminas.md @@ -236,7 +236,7 @@ When using the [Loggable](../loggable.md), [Translatable](../translatable.md), o need to register the mappings for these extensions to your object managers. > [!NOTE] -> These extensions only provide mappings through annotations or attributes; if using annotations, you will need to ensure the deprecated [`doctrine/annotations`](https://www.doctrine-project.org/projects/annotations.html) library is installed and configured. +> These extensions only provide mappings through annotations or attributes, with support for annotations being deprecated. If using annotations, you will need to ensure the [`doctrine/annotations`](https://www.doctrine-project.org/projects/annotations.html) library is installed and configured. ### MongoDB ODM Mapping diff --git a/doc/frameworks/symfony.md b/doc/frameworks/symfony.md index a2a98a6587..dd910318a8 100644 --- a/doc/frameworks/symfony.md +++ b/doc/frameworks/symfony.md @@ -242,7 +242,7 @@ When using the [Loggable](../loggable.md), [Translatable](../translatable.md), o need to register the mappings for these extensions to your object managers. > [!NOTE] -> These extensions only provide mappings through annotations or attributes; if using annotations, you will need to ensure the deprecated [`doctrine/annotations`](https://www.doctrine-project.org/projects/annotations.html) library is installed and enabled. +> These extensions only provide mappings through annotations or attributes, with support for annotations being deprecated. If using annotations, you will need to ensure the [`doctrine/annotations`](https://www.doctrine-project.org/projects/annotations.html) library is installed and configured. ### MongoDB ODM Mapping