alice icon indicating copy to clipboard operation
alice copied to clipboard

UniqueValueResolver's deep_copy calls prevent relation resolving in entity managers

Open func0der opened this issue 3 years ago • 2 comments

Hey there,

I think I came to the right place for this, though my usecase might be doctrine-specific.

Given the following fixture set:

Main\V1\Entity\Permission:
    permission_text:
        name: 'text'
    permission_email:
        name: 'email'
    permission_user:
        name: 'user'
    permission_admin:
        name: 'admin'

Main\V1\Entity\User:
    user_random:
        username: 'random'
        permissions (unique): 3x @permission_*

And the following tables in the database:

CREATE TABLE `permission` (
  `permission_id` int(11) NOT NULL AUTO_INCREMENT,
  `permission_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`permission_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

CREATE TABLE `user` (
  `user_id` int(11) NOT NULL AUTO_INCREMENT,
  `user_username` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`user_id`),
  UNIQUE KEY `user_username` (`user_username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

CREATE TABLE `userpermission` (
  `userpermission_user_id` int(11) NOT NULL,
  `userpermission_permission_id` int(11) NOT NULL,
  PRIMARY KEY (`userpermission_user_id`,`userpermission_permission_id`),
  KEY `IDX_AD35BE53A4C53F09` (`userpermission_user_id`),
  KEY `IDX_AD35BE53E175D071` (`userpermission_permission_id`),
  CONSTRAINT `FK_AD35BE53A4C53F09` FOREIGN KEY (`userpermission_user_id`) REFERENCES `user` (`user_id`),
  CONSTRAINT `FK_AD35BE53E175D071` FOREIGN KEY (`userpermission_permission_id`) REFERENCES `permission` (`permission_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

We see that that userpermission has primary key that consists of the two foreign keys combined. This means that the combination of those two is meant to be unique. This is why, I can not simply write permissions: 3x @permission_* in the Main\V1\Entity\User fixture, but need to have unique values for this case.

When I am using unique here, which I know make the fixture unique across the whole fixture set, the database table permission will contain the four entries from the Main\V1\Entity\Permission fixture AND as duplicates the three that are used in the Main\V1\Entity\User fixture's line: permissions (unique): 3x @permission_*.

I know from Doctrine that is store references to managed objects by the spl_object_hash of objects. Since the \Nelmio\Alice\Definition\Value\UniqueValue deep_clones the object, a new object is created which therefor has another spl_object_hash, which messes up the reference. By the way: \Nelmio\Alice\Definition\Value\UniqueValue does this in the __constructor and in getValue(). Shouldn't one time be enough? :thinking:

I would figure that this, if not intended, does not play well with other entity mangers as well.

Is this intended behavior?

And if so, how would you go about to have an isolated unique case. (i know, this is a question not a bug report and kinda off-topic).

func0der avatar May 04 '21 11:05 func0der

I know from Doctrine that is store references to managed objects by the spl_object_hash of objects. Since the \Nelmio\Alice\Definition\Value\UniqueValue deep_clones the object, a new object is created which therefor has another spl_object_hash, which messes up the reference.

I do not think this should be an issue as alice there takes fixtures and outputs objects, although there might be deep cloning within those objects should not be known by Doctrine yet. Or do you mean this is happening for injected objects?

theofidry avatar May 11 '21 06:05 theofidry

If by "injcted objects" you mean those, you can add additionally to the ones created from fixtures files, no.

The fact that Doctrine does not know about the objects at that point in time, does not matter for this issue.

The object generated for permission_text has for example the the object hash 1234. If that fixture object is chosen by the user_random fixture, it is cloned by UniqueValue, which changes its object hash to abcd. So the objects might be equal but not the same, which will is a problem for the entity managers (e.g. Doctrine).

I hope this shows what the problem is.

func0der avatar May 14 '21 13:05 func0der