-
-
Notifications
You must be signed in to change notification settings - Fork 166
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Event properties matching ShouldBeStored methods are not serialized correctly #475
Comments
As a quick fix, we wrote a custom ObjectNormalizer and replaced it in event_normalizers array in config, this fixes the issue namespace App\Support;
use Spatie\EventSourcing\Support\ObjectNormalizer as BaseObjectNormalizer;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use Symfony\Component\PropertyInfo\PropertyReadInfoExtractorInterface;
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorResolverInterface;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Symfony\Component\PropertyInfo\PropertyReadInfo;
class ObjectNormalizer extends BaseObjectNormalizer
{
public function __construct(?ClassMetadataFactoryInterface $classMetadataFactory = null, ?NameConverterInterface $nameConverter = null, ?PropertyAccessorInterface $propertyAccessor = null, ?PropertyTypeExtractorInterface $propertyTypeExtractor = null, ?ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null, ?callable $objectClassResolver = null, array $defaultContext = [])
{
// We need to customize how properties are accessed during normalization
// to prevent methods from being preferred over properties. This causes
// issues with events that have property named eg. `createdAt` because
// method with the same name already exists on ShouldBeStored class
$readInfoExtractor = new class implements PropertyReadInfoExtractorInterface {
protected ReflectionExtractor $reflectionExtractor;
public function __construct()
{
$this->reflectionExtractor = new ReflectionExtractor([], null, null, false);
}
public function getReadInfo(string $class, string $property, array $context = []): ?PropertyReadInfo
{
$context['enable_getter_setter_extraction'] = false;
return $this->reflectionExtractor->getReadInfo($class, $property, $context);
}
};
$propertyAccessor = PropertyAccess::createPropertyAccessorBuilder()
->setReadInfoExtractor($readInfoExtractor)
->getPropertyAccessor();
parent::__construct(
$classMetadataFactory,
$nameConverter,
$propertyAccessor,
$propertyTypeExtractor,
$classDiscriminatorResolver,
$objectClassResolver,
$defaultContext,
);
}
} Then, in 'event_normalizers' => [
Spatie\EventSourcing\Support\CarbonNormalizer::class,
Spatie\EventSourcing\Support\ModelIdentifierNormalizer::class,
Symfony\Component\Serializer\Normalizer\DateTimeNormalizer::class,
Symfony\Component\Serializer\Normalizer\ArrayDenormalizer::class,
Symfony\Component\Serializer\Normalizer\BackedEnumNormalizer::class,
App\Support\ObjectNormalizer::class,
], |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is due to how Symfony serializer works. When the serialized object (event) contains a method with the name of the attribute, return value of that method is preferred and the value of the attribute is ignored.
The simplest example of this is declaring a Carbon property named
createdAt
. When an event with this property is stored with a value different from now, the provided value is ignored and instead the event is saved in the database with the current time being the value of this property (which is the return value of the createdAt method on ShouldBeStored)The text was updated successfully, but these errors were encountered: