DoctrineORMModule Documentation

repository·6.4.x·Indexed 19 days ago

https://github.com/doctrine/doctrineormmodule

A Laminas integration package providing support for Doctrine ORM. It enables the configuration of multiple entity managers and DBAL connections, PDO connection reuse, and integration with Laminas Form elements and hydrators. The module includes detailed configuration options for Doctrine Migrations, ORM cache adapters (including Redis), Second Level Cache, custom DQL functions, custom types, and DBAL 3.x middlewares.

Tokens
15.5K
Snippets
45
Records
47
Agent score
65%

What's inside DoctrineORMModule

  1. Overview of DoctrineORMModule features

    6.4.x

    The DoctrineORMModule integrates Doctrine ORM with the Laminas framework. It provides several key capabilities out of the box:

    • Doctrine ORM support: Seamless integration of the ORM into the Laminas ecosystem.
    • Multiple ORM entity managers: Support for managing multiple entity managers within a single application.
    • Multiple DBAL connections: Ability to configure and use multiple Database Abstraction Layer (DBAL) connections.
    • PDO connection reuse: The ability to reuse existing PDO connections within a DBAL connection.
  2. Use the DoctrineObject authentication adapter

    6.4.x

    The DoctrineModule\Authentication\Adapter\DoctrineObject provides an adapter for Laminas\Authentication that works with Doctrine entities. It functions similarly to the core framework's DbTable adapter but operates on entities via the Entity Manager.

    To use it, you must provide:

    1. The EntityManager instance.
    2. The entity class name.
    3. The identity field name.
    4. The credential field name.
    5. (Optional) A callable to handle password hashing/validation logic before checking credentials.
    <?php
    
    use DoctrineModule\Authentication\Adapter\DoctrineObject as DoctrineObjectAdapter;
    
    $adapter = DoctrineObjectAdapter(
        $entityManager,
        'Application\Test\Entity',
        'username', // identity field
        'password', // credential field
        function($identity, $credential) { // optional callable for hashing
            return \Application\Service\User::hashCredential(
                $credential,
                $identity->getSalt(),
                $identity->getAlgorithm()
            );
        }
    );
    
    $adapter->setIdentityValue('admin');
    $adapter->setCredentialValue('password');
    $result = $adapter->authenticate();
    
    echo $result->isValid() ? 'Authenticated' : 'Could not authenticate';
  3. How to Use a Quote Strategy

    6.4.x

    To use a custom quote strategy (e.g., AnsiQuoteStrategy), register the strategy class as an invokable in the Laminas service_manager, then assign it to the quote_strategy key in the orm_default configuration.

    return [
        'service_manager' => [
            'invokables' => [
                \Doctrine\ORM\Mapping\AnsiQuoteStrategy::class => \Doctrine\ORM\Mapping\AnsiQuoteStrategy::class,
            ],
        ],
        'doctrine' => [
            'configuration' => [
                'orm_default' => [
                    'quote_strategy' => \Doctrine\ORM\Mapping\AnsiQuoteStrategy::class,
                ],
            ],
        ],
    ];
  4. Install the Doctrine ORM Module

    6.4.x

    Install the module using Composer by running the following command:

    composer require doctrine/doctrine-orm-module

    After installation, you must:

    1. Add DoctrineModule and DoctrineORMModule to your config/application.config.php.
    2. Create the directory data/DoctrineORMModule/Proxy.
    3. Ensure your application has write access to the data/DoctrineORMModule/Proxy directory.
  5. How to add a Custom Type

    6.4.x

    Adding a custom type involves two steps: registering the type implementation with the ORM and then mapping it to the underlying database platform.

    1. Register the type implementation: Extend Doctrine\DBAL\Types\Type and register it under types in the orm_default configuration. Note: If your type uses a database type already mapped by Doctrine, override requiresSQLCommentHint() in your type class to return true to ensure Doctrine can distinguish it.

    2. Register the type mapping: Map the custom type name to itself in the doctrine_type_mappings section of the connection configuration.

    // 1. Register implementation
    return [
        'doctrine' => [
            'configuration' => [
                'orm_default' => [
                    'types' => [
                        'newtype' => \My\Types\NewType::class,
                    ],
                ],
            ],
        ],
    ];
    
    // 2. Register mapping
    return [
        'doctrine' => [
            'connection' => [
                'orm_default' => [
                    'doctrine_type_mappings' => [
                        'mytype' => 'mytype',
                    ],
                ],
            ],
        ],
    ];
  6. Integrate DoctrineORMModule with Laminas Developer Tools

    6.4.x

    You can use Laminas Developer Tools to track performance pitfalls and monitor the amount of queries performed by the ORM. When Laminas\DeveloperTools is enabled and you are using doctrine.entity_manager.orm_default as your default EntityManager, queries performed by the ORM are automatically logged and displayed in the developer toolbar.

    To set this up:

    1. Install laminas/laminas-developer-tools via Composer.
    2. Enable Laminas\DeveloperTools in your application modules.
    3. Enable profiling and the toolbar within the Laminas Developer Tools configuration.
    composer require laminas/laminas-developer-tools
  7. How to Use Two Connections

    6.4.x

    To use multiple database connections, you must define separate configurations for each connection across several service manager keys. For a connection named orm_crawler, you need to define:

    • doctrine.connection.orm_crawler: Connection parameters (driver, host, user, etc.).
    • doctrine.configuration.orm_crawler: ORM configuration (caches, proxy settings, etc.).
    • doctrine.driver.orm_crawler: Metadata drivers (e.g., Annotation or DriverChain).
    • doctrine.entitymanager.orm_crawler: Links the specific connection and configuration.
    • doctrine.eventmanager.orm_crawler, doctrine.sql_logger_collector.orm_crawler, and doctrine.entity_resolver.orm_crawler.

    The AbstractDoctrineServiceFactory will automatically create these objects. You can then retrieve them from the Laminas Service Manager using the keys doctrine.connection.orm_crawler, doctrine.entitymanager.orm_crawler, etc.

    return [
        'doctrine' => [
            'connection' => [
                'orm_crawler' => [
                    'driverClass'   => \Doctrine\DBAL\Driver\PDO\MySQL\Driver::class,
                    'eventmanager'  => 'orm_crawler',
                    'configuration' => 'orm_crawler',
                    'params'        => [
                        'host'     => 'localhost',
                        'port'     => '3306',
                        'user'     => 'root',
                        'password' => 'root',
                        'dbname'   => 'crawler',
                        'driverOptions' => [
                            1002 => 'SET NAMES utf8',
                        ],
                    ],
                ],
            ],
    
            'configuration' => [
                'orm_crawler' => [
                    'metadata_cache'    => 'array',
                    'query_cache'       => 'array',
                    'result_cache'      => 'array',
                    'hydration_cache'   => 'array',
                    'driver'            => 'orm_crawler_chain',
                    'generate_proxies'  => true,
                    'proxy_dir'         => 'data/DoctrineORMModule/Proxy',
                    'proxy_namespace'   => 'DoctrineORMModule\Proxy',
                    'filters'           => [],
                ],
            ],
    
            'driver' => [
                'orm_crawler_annotation' => [
                    'class' => \Doctrine\ORM\Mapping\Driver\AnnotationDriver::class,
                    'cache' => 'array',
                    'paths' => [
                        __DIR__ . '/../src/Crawler/Entity',
                    ],
                ],
                'orm_crawler_chain' => [
                    'class'   => \Doctrine\ORM\Mapping\Driver\DriverChain::class,
                    'drivers' => [
                        'Crawler\Entity' =>  'orm_crawler_annotation',
                    ],
                ],
            ],
    
            'entitymanager' => [
                'orm_crawler' => [
                    'connection'    => 'orm_crawler',
                    'configuration' => 'orm_crawler',
                ],
            ],
    
            'eventmanager' => [
                'orm_crawler' => [],
            ],
    
            'sql_logger_collector' => [
                'orm_crawler' => [],
            ],
    
            'entity_resolver' => [
                'orm_crawler' => [],
            ],
        ],
    ];
  8. How to Use a Naming Strategy

    6.4.x

    To use a custom naming strategy (e.g., UnderscoreNamingStrategy), register the strategy class as an invokable in the Laminas service_manager, then assign it to the naming_strategy key in the orm_default configuration.

    return [
        'service_manager' => [
            'invokables' => [
                \Doctrine\ORM\Mapping\UnderscoreNamingStrategy::class => \Doctrine\ORM\Mapping\UnderscoreNamingStrategy::class,
            ],
        ],
        'doctrine' => [
            'configuration' => [
                'orm_default' => [
                    'naming_strategy' => \Doctrine\ORM\Mapping\UnderscoreNamingStrategy::class,
                ],
            ],
        ],
    ];
  9. Configure Redis as a Doctrine cache provider

    6.4.x

    To use Redis for caching, you must define a service factory in your module.config.php to create the Redis instance, then map the doctrine.cache.redis configuration to that service. Finally, assign 'redis' as the adapter for the desired ORM cache types.

    // module.config.php
    namespace Db;
    
    return [
        'service_manager' => [
            'factories' => [
                 'Db\Cache\Redis' => Db\Cache\RedisFactory::class,
            ],
        ],
        'doctrine' => [
            'cache' => [
                'redis' => [
                    'namespace' => 'Db_Doctrine',
                    'instance'  => 'Db\Cache\Redis',
                ],
            ],
            'configuration' => [
                'orm_default' => [
                    'query_cache'       => 'redis',
                    'result_cache'      => 'redis',
                    'metadata_cache'    => 'redis',
                    'hydration_cache'   => 'redis',
                ],
            ],
        ],
    ];
    
    // Example RedisFactory implementation
    namespace Db\Cache;
    
    use Psr\Container\ContainerInterface;
    use Redis;
    
    class RedisFactory
    {
        public function __invoke(
            ContainerInterface $container,
            $requestedName,
            array $options = null
        ) {
            $redis = new Redis(); 
            $redis->connect('127.0.0.1', 6379);
    
            return $redis;
        }
    }
  10. Create forms from Doctrine entities using EntityBasedFormBuilder

    6.4.x

    You can automatically generate Laminas forms based on your Doctrine entity definitions using EntityBasedFormBuilder. This builder leverages either PHP8 attributes or DocBlock annotations to map entity properties to form elements.

    To use PHP8 attributes, you must explicitly provide an AttributeBuilder to the EntityBasedFormBuilder constructor. Otherwise, it defaults to using DocBlock annotations via AnnotationBuilder.

    Once the builder is initialized, you can use it to either retrieve a form specification array or instantiate a full Laminas orm object directly from an entity instance.

    // 1. Initialize the EntityManager
    $entityManager = $container->get(\Doctrine\ORM\EntityManager::class);
    
    // 2. Setup the builder (using PHP8 attributes as an example)
    $attributeBuilder = new \Laminas\Form\Annotation\AttributeBuilder();
    $builder = new \DoctrineORMModule\Form\Annotation\EntityBasedFormBuilder($entityManager, $attributeBuilder);
    
    // 3. Create the form from an entity instance
    $entity = new User();
    
    // Option A: Get the form specification (array)
    $formSpec = $builder->getFormSpecification($entity);
    
    // Option B: Get the actual form instance
    $form = $builder->createForm($entity);
  11. Using DBAL Middlewares

    6.4.x

    If you are using DBAL 3.x, you can register custom middlewares. This feature has no effect on DBAL 2.x. You must first register the middleware classes as invokables in the Laminas service_manager, then list them in the middlewares array under your connection's configuration (e.g., test_default).

    return [
        'service_manager' => [
            'invokables' => [
                \My\Middlewares\CustomMiddleware::class => \My\Middlewares\CustomMiddleware::class,
                \My\Middlewares\AnotherCustomMiddleware::class => \My\Middlewares\AnotherCustomMiddleware::class,
            ],
        ],
        'doctrine' => [
            'configuration' => [
                'test_default' => [
                    'middlewares' => [
                        \My\Middlewares\CustomMiddleware::class,
                        \My\Middlewares\AnotherCustomMiddleware::class,
                    ],
                ],
            ],
        ],
    ];