You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Doctrine doesn't detect changes at columnDefinition, but Doctrine detects mapping's changes if comment changed. The solution is to add virtual comment with value based on hash of columnDefinition:
<?php
declare(strict_types=1);
namespace RootNs\Entity\Attributes;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
final class ColumnDefinitionHashComment
{
}
<?php
declare(strict_types=1);
namespace RootNs\EventListener;
use Doctrine\ORM\Mapping as ORM;
use RootNs\Entity\Attributes\ColumnDefinitionHashComment;
#[ORM\Entity]
#[ORM\Table(name: 'users')]
class User
{
#[ORM\Id]
#[ORM\Column(name: 'id', type: 'uuid', unique: true, nullable: false)]
private UuidInterface $id;
#[ORM\Column(type: 'json_document', options: [
'jsonb' => true,
])]
private UserData $data;
#[ColumnDefinitionHashComment]
#[ORM\Column(
type: 'integer',
nullable: false,
insertable: false,
updatable: false,
columnDefinition: 'INT GENERATED ALWAYS AS (JSON_VALUE(data, "$.id")) NOT NULL',
)]
private readonly int $relationId;
}
<?php
declare(strict_types=1);
namespace RootNs\EventListener;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
use Doctrine\ORM\Mapping\FieldMapping;
use RootNs\Entity\Attributes\ColumnDefinitionHashComment;
use ReflectionProperty;
class ColumnDefinitionHashCommentSubscriber
{
public function loadClassMetadata(LoadClassMetadataEventArgs $event): void
{
$classMetadata = $event->getClassMetadata();
foreach ($classMetadata->fieldMappings as $fieldName => $fieldMapping) {
$reflectionProperty = $classMetadata->reflClass->getProperty($fieldName);
assert(null !== $reflectionProperty);
$attributes = $reflectionProperty->getAttributes(ColumnDefinitionHashComment::class);
if ([] === $attributes) {
continue;
}
$this->addColumnDefinitionCommentHash($classMetadata->getName(), $reflectionProperty, $fieldMapping);
}
}
private function addColumnDefinitionCommentHash(
string $className,
ReflectionProperty $reflectionProperty,
FieldMapping $fieldMapping
): void {
if (null === $fieldMapping->columnDefinition) {
throw new \LogicException(sprintf(
'At entity field %s:%s columnDefinition must be defined',
$className,
$reflectionProperty->getName()
));
}
if (false !== strripos($fieldMapping->columnDefinition, 'comment')) {
throw new \LogicException(sprintf(
'At entity field %s:%s comment must not be at columnDefinition',
$className,
$reflectionProperty->getName()
));
}
// xxh3 - is the fastest supported algorithm in php: https://php.watch/articles/php-hash-benchmark
$fieldMapping->options['comment'] = sprintf(
'(columnDefinitionHash:%s)',
hash('xxh3', $fieldMapping->columnDefinition)
);
$fieldMapping->columnDefinition .= sprintf(' COMMENT "%s"', $fieldMapping->options['comment']);
}
}
The text was updated successfully, but these errors were encountered:
Feature Request
Summary
Doctrine doesn't detect changes at
columnDefinition
: https://www.doctrine-project.org/projects/doctrine-orm/en/3.2/reference/attributes-reference.html#columnDirty solution
Doctrine doesn't detect changes at
columnDefinition
, but Doctrine detects mapping's changes if comment changed. The solution is to add virtual comment with value based on hash ofcolumnDefinition
:columnDefinition
changed ->hash(columnDefinition)
changed -> comment changed -> Doctrine detect mapping's changesTested example
The text was updated successfully, but these errors were encountered: