-
-
Notifications
You must be signed in to change notification settings - Fork 455
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Enable
@CustomIdGenerator()
to reference services tagged as "doctri…
…ne.id_generator"
- Loading branch information
1 parent
91f0139
commit e174049
Showing
13 changed files
with
356 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
<?php | ||
|
||
namespace Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler; | ||
|
||
use Doctrine\Bundle\DoctrineBundle\Mapping\ClassMetadataFactory; | ||
use Doctrine\Bundle\DoctrineBundle\Mapping\MappingDriver; | ||
use Doctrine\ORM\Mapping\ClassMetadataFactory as ORMClassMetadataFactory; | ||
use Symfony\Component\DependencyInjection\Alias; | ||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; | ||
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; | ||
use Symfony\Component\DependencyInjection\ContainerBuilder; | ||
use Symfony\Component\DependencyInjection\Reference; | ||
|
||
final class IdGeneratorPass implements CompilerPassInterface | ||
{ | ||
const ID_GENERATOR_TAG = 'doctrine.id_generator'; | ||
const CONFIGURATION_TAG = 'doctrine.orm.configuration'; | ||
|
||
public function process(ContainerBuilder $container): void | ||
{ | ||
$generatorIds = array_keys($container->findTaggedServiceIds(self::ID_GENERATOR_TAG)); | ||
|
||
// when ORM is not enabled | ||
if (! $container->hasDefinition('doctrine.orm.configuration') || ! $generatorIds) { | ||
return; | ||
} | ||
|
||
$generatorRefs = array_map(static function ($id) { | ||
return new Reference($id); | ||
}, $generatorIds); | ||
|
||
$ref = ServiceLocatorTagPass::register($container, array_combine($generatorIds, $generatorRefs)); | ||
$container->setAlias('doctrine.id_generator_locator', new Alias((string) $ref, false)); | ||
|
||
foreach ($container->findTaggedServiceIds(self::CONFIGURATION_TAG) as $id => $tags) { | ||
$configurationDef = $container->getDefinition($id); | ||
$methodCalls = $configurationDef->getMethodCalls(); | ||
$metadataDriverImpl = null; | ||
|
||
foreach ($methodCalls as $i => [$method, $arguments]) { | ||
if ($method === 'setMetadataDriverImpl') { | ||
$metadataDriverImpl = (string) $arguments[0]; | ||
} | ||
|
||
if ($method !== 'setClassMetadataFactoryName') { | ||
continue; | ||
} | ||
|
||
if ($arguments[0] !== ORMClassMetadataFactory::class && $arguments[0] !== ClassMetadataFactory::class) { | ||
$class = $container->getReflectionClass($arguments[0]); | ||
|
||
if ($class && $class->isSubclassOf(ClassMetadataFactory::class)) { | ||
break; | ||
} | ||
|
||
continue 2; | ||
} | ||
|
||
$methodCalls[$i] = ['setClassMetadataFactoryName', [ClassMetadataFactory::class]]; | ||
} | ||
|
||
if ($metadataDriverImpl === null) { | ||
continue; | ||
} | ||
|
||
$configurationDef->setMethodCalls($methodCalls); | ||
$container->register('.' . $metadataDriverImpl, MappingDriver::class) | ||
->setDecoratedService($metadataDriverImpl) | ||
->setArguments([ | ||
new Reference(sprintf('.%s.inner', $metadataDriverImpl)), | ||
new Reference('doctrine.id_generator_locator'), | ||
]); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?php | ||
|
||
namespace Doctrine\Bundle\DoctrineBundle\Mapping; | ||
|
||
use Doctrine\ORM\Mapping\ClassMetadata; | ||
use Doctrine\ORM\Mapping\ClassMetadataFactory as BaseClassMetadataFactory; | ||
|
||
class ClassMetadataFactory extends BaseClassMetadataFactory | ||
{ | ||
/** | ||
* {@inheritDoc} | ||
*/ | ||
protected function doLoadMetadata($class, $parent, $rootEntityFound, array $nonSuperclassParents): void | ||
{ | ||
parent::doLoadMetadata($class, $parent, $rootEntityFound, $nonSuperclassParents); | ||
|
||
$customGeneratorDefinition = $class->customGeneratorDefinition; | ||
|
||
if (! isset($customGeneratorDefinition['instance'])) { | ||
return; | ||
} | ||
|
||
$class->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_CUSTOM); | ||
$class->setIdGenerator($customGeneratorDefinition['instance']); | ||
unset($customGeneratorDefinition['instance']); | ||
$class->setCustomGeneratorDefinition($customGeneratorDefinition); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
<?php | ||
|
||
namespace Doctrine\Bundle\DoctrineBundle\Mapping; | ||
|
||
use Doctrine\ORM\Mapping\ClassMetadataInfo; | ||
use Doctrine\Persistence\Mapping\ClassMetadata; | ||
use Doctrine\Persistence\Mapping\Driver\MappingDriver as MappingDriverInterface; | ||
use Psr\Container\ContainerInterface; | ||
|
||
class MappingDriver implements MappingDriverInterface | ||
{ | ||
/** @var MappingDriverInterface */ | ||
private $driver; | ||
|
||
/** @var ContainerInterface */ | ||
private $idGeneratorLocator; | ||
|
||
public function __construct(MappingDriverInterface $driver, ContainerInterface $idGeneratorLocator) | ||
{ | ||
$this->driver = $driver; | ||
$this->idGeneratorLocator = $idGeneratorLocator; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function getAllClassNames() | ||
{ | ||
return $this->driver->getAllClassNames(); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function isTransient($className): bool | ||
{ | ||
return $this->driver->isTransient($className); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function loadMetadataForClass($className, ClassMetadata $metadata): void | ||
{ | ||
$this->driver->loadMetadataForClass($className, $metadata); | ||
|
||
if ( | ||
$metadata->generatorType !== ClassMetadataInfo::GENERATOR_TYPE_CUSTOM | ||
|| ! isset($metadata->customGeneratorDefinition['class']) | ||
|| ! $this->idGeneratorLocator->has($metadata->customGeneratorDefinition['class']) | ||
) { | ||
return; | ||
} | ||
|
||
$idGenerator = $this->idGeneratorLocator->get($metadata->customGeneratorDefinition['class']); | ||
$metadata->setCustomGeneratorDefinition(['instance' => $idGenerator] + $metadata->customGeneratorDefinition); | ||
$metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_NONE); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
Custom ID Generators | ||
==================== | ||
|
||
Custom ID generators are classes that allow implementing custom logic to generate | ||
identifiers for your entities. They extend ``Doctrine\ORM\Id\AbstractIdGenerator`` | ||
and implement the custom logic in the ``generate(EntityManager $em, $entity)`` | ||
method. Before Doctrine bundle 2.3, custom ID generators were always created | ||
without any constructor arguments. | ||
|
||
Starting with Doctrine bundle 2.3, the ``CustomIdGenerator`` annotation can be | ||
used to reference any services tagged with the ``doctrine.id_generator`` tag. | ||
If you enable autoconfiguration (which is the default most of the time), Symfony | ||
will add this tag for you automatically if you implement your own id-generators. | ||
|
||
When using Symfony's Doctrine bridge and Uid component 5.3 or higher, two services | ||
are provided: ``doctrine.ulid_generator`` to generate ULIDs, and | ||
``doctrine.uuid_generator`` to generate UUIDs. | ||
|
||
.. code-block:: php | ||
|
||
<?php | ||
// User.php | ||
|
||
use Doctrine\ORM\Mapping as ORM; | ||
|
||
/** | ||
* @ORM\Entity | ||
*/ | ||
class User | ||
{ | ||
/** | ||
* @Id | ||
* @Column(type="uuid") | ||
* @ORM\GeneratedValue(strategy="CUSTOM") | ||
* @ORM\CustomIdGenerator('doctrine.uuid_generator') | ||
*/ | ||
private $id; | ||
|
||
// .... | ||
} | ||
|
||
See also | ||
https://www.doctrine-project.org/projects/doctrine-orm/en/2.8/reference/annotations-reference.html#annref_customidgenerator | ||
for more info about custom ID generators. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.