Skip to content

Recursively providing DataSubjectId for PersonalData in nested objects? #114

Closed

Description

@wikando-ck

Hi David & Daniel,
I'm using the package along with the event-sourcing bundle.

I stumbled upon the following case:

use Patchlevel\EventSourcing\Attribute\Event;
use Patchlevel\Hydrator\Attribute\DataSubjectId;
use Patchlevel\Hydrator\Attribute\PersonalData;

#[Event(name: 'some_event')]
final readonly class SomeEvent
{
    public function __construct(
        #[DataSubjectId]
        public int $id,
        public NestedData $data
    )
    {}
}

final readonly class NestedData
{
    public function __construct(
        public string $someFieldRequiredAfterCipherDestruction,
        #[PersonalData]
        public string $somePersonalData
    )
    {}
}

This would fail, as there is no DataSubjectId in the NestedData.
NestedData can be some immutable VO from my Domain, that I don't want to modify and it should not have an identifier.
So, to allow storing it, I'd need the hydrator to pass a DataSubjectId recursively into nested calls.
I've seen the work on named DataSubjectIds for 2.x, so this would not just be one DataSubjectId but a container that holds them.

I can also imagine that it'd be handy to have a way to tell the hydrator to use the aggregate id from the event surrounding the hydration as DataSubjectId.
Maybe as an attribute targeting classes: #[DataSubjectId(useAggregateId: true)]

I'd love to know your opinion about these.
Maybe there's something i'm not aware of to achieve this already?

Activity

  1. DanielBadura commented on Oct 21, 2025

    @DanielBadura
    Member

    I think this can be a valid use case regarding the value object with nested data but i think the implementation could be a bit tricky 😅. I'm not sure how this could look like right now. As of right now, each object is handled in isolation, there is no context available if this object is now hydrated as part of another object or standalone.

    The second part about the extra option #[DataSubjectId(useAggregateId: true)], i could not grasp it completely i think. Do you mean something like this as an alternative solution?:

    #[Event(name: 'some_event')]
    final readonly class SomeEvent
    {
        public function __construct(
            #[DataSubjectId]
            public int $id,
            public NestedData $data
        )
        {}
    }
    
    #[DataSubjectId(useAggregateId: true)]
    final readonly class NestedData
    {
        public function __construct(
            public string $someFieldRequiredAfterCipherDestruction,
            #[PersonalData]
            public string $somePersonalData
        )
        {}
    }
  2. wikando-ck commented on Oct 21, 2025

    @wikando-ck
    ContributorAuthor

    Yes that'd be the use-case, or we could use the #[Id] instead of #[DataSubjectId], but that would mix in concepts from the event-sourcing bundle into the hydrator, right?

    Yeah I was hopping through the process with Xdebug a little bit.
    The isolation is nice and implementing this could lead to unwanted complexity.
    My use-case is not possible without it, but then again one can argue in favour of using events as rather flat, dto-style concepts.
    That bloats up the mapping to domain objects when applying though.

    I've had this idea for an approach: Symfony serializer keeps track of object trees in some kind of metadata.
    For this rather flat example, this would look like:

    SomeEvent.NestedData.somePersonalData
    

    The method to get a subjectId could walk left on this tree and use the first subjectId that is available.
    This would also allow named subjectIds.

  3. DanielBadura commented on Nov 29, 2025

    @DanielBadura
    Member

    Just as a heads up: We are currently working on #130 which should enable nested knowledge about e.g. #[DataSubjectId].

  4. ckrack commented on Feb 10, 2026

    @ckrack

    Is there anything I can help on this?

  5. DanielBadura commented on Feb 11, 2026

    @DanielBadura
    Member

    I'll notify you again when we are ready, then you could help us to test it. We needed to refactor a lot to get this performant working. This PR should be the last one to get it working: #134

  6. DavidBadura commented on Feb 23, 2026

    @DavidBadura
    Member

    This feature will be released with version 2.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions