-
-
Notifications
You must be signed in to change notification settings - Fork 75
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
fix: can create inversed one to one #659
base: 2.x
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ | |
use Doctrine\ORM\Mapping\ClassMetadata; | ||
use Doctrine\ORM\Mapping\InverseSideMapping; | ||
use Doctrine\ORM\Mapping\MappingException as ORMMappingException; | ||
use Doctrine\ORM\Mapping\ToManyAssociationMapping; | ||
use Doctrine\Persistence\Mapping\MappingException; | ||
use Zenstruck\Foundry\Persistence\RelationshipMetadata; | ||
|
||
|
@@ -47,8 +48,9 @@ public function relationshipMetadata(string $parent, string $child, string $fiel | |
} | ||
|
||
return new RelationshipMetadata( | ||
isCascadePersist: $association->isCascadePersist(), | ||
isCascadePersist: ($inversedAssociation ?? $association)->isCascadePersist(), | ||
inverseField: $metadata->isSingleValuedAssociation($association->fieldName) ? $association->fieldName : null, | ||
isCollection: ($inversedAssociation ?? $association) instanceof ToManyAssociationMapping | ||
Comment on lines
+51
to
+53
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure about those... but we want to know if the "inversed" association is a collection here, if it exsts. It's the only way to know that we are handling an "inverse one to one" |
||
); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -275,8 +275,25 @@ protected function normalizeParameter(string $field, mixed $value): mixed | |
$value->persist = $this->persist; // todo - breaks immutability | ||
} | ||
|
||
if ($value instanceof self && Configuration::instance()->persistence()->relationshipMetadata(static::class(), $value::class(), $field)?->isCascadePersist) { | ||
$value->persist = false; | ||
if ($value instanceof self) { | ||
$pm = Configuration::instance()->persistence(); | ||
|
||
$relationshipMetadata = $pm->relationshipMetadata($value::class(), static::class(), $field); | ||
|
||
// handle inversed OneToOne | ||
if ($relationshipMetadata && !$relationshipMetadata->isCollection && $inverseField = $relationshipMetadata->inverseField) { | ||
$this->tempAfterPersist[] = static function(object $object) use ($value, $inverseField, $pm) { | ||
$value->create([$inverseField => $object]); | ||
$pm->refresh($object); | ||
}; | ||
|
||
// creation delegated to afterPersist hook - return empty array here | ||
return null; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm wondering if it is OK to return null here. EDIT: I think it can: #[Entity]
class Contact
{
#[ORM\OneToOne(targetEntity: Address::class, inversedBy: 'contact')]
#[ORM\JoinColumn(nullable: false)]
public Address $address;
public function __construct()
{
$this->address = new Address($this);
}
}
#[Entity]
class Address
{
public function __construct(
#[ORM\OneToOne(targetEntity: Contact::class, mappedBy: 'address')]
public Contact $contact;
) {}
} and then, it would not be valid to return There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this very specific case, where both side of Also, maybe we could find a way to return something else than BTW, I just figured out that you did notice this case was error prone: https://github.com/zenstruck/foundry/blob/2.x/tests/Integration/ORM/EntityFactoryRelationshipTestCase.php#L183 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I don't remember the exact context of what happened but I think you're right, it's the circular dependency issue. |
||
} | ||
|
||
if (Configuration::instance()->persistence()->relationshipMetadata(static::class(), $value::class(), $field)?->isCascadePersist) { | ||
$value->persist = false; | ||
} | ||
} | ||
|
||
return unproxy(parent::normalizeParameter($field, $value)); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,11 +13,15 @@ | |
|
||
use Doctrine\ORM\Mapping as ORM; | ||
use Zenstruck\Foundry\Tests\Fixture\Entity\Address; | ||
use Zenstruck\Foundry\Tests\Fixture\Entity\Contact; | ||
use Zenstruck\Foundry\Tests\Fixture\Entity\Contact\CascadeContact; | ||
|
||
/** | ||
* @author Kevin Bond <[email protected]> | ||
*/ | ||
#[ORM\Entity] | ||
class CascadeAddress extends Address | ||
{ | ||
#[ORM\OneToOne(targetEntity: CascadeContact::class, mappedBy: 'address', cascade: ['persist', 'remove'])] | ||
protected Contact|null $contact = null; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,11 +13,15 @@ | |
|
||
use Doctrine\ORM\Mapping as ORM; | ||
use Zenstruck\Foundry\Tests\Fixture\Entity\Address; | ||
use Zenstruck\Foundry\Tests\Fixture\Entity\Contact; | ||
use Zenstruck\Foundry\Tests\Fixture\Entity\Contact\StandardContact; | ||
|
||
/** | ||
* @author Kevin Bond <[email protected]> | ||
*/ | ||
#[ORM\Entity] | ||
class StandardAddress extends Address | ||
{ | ||
#[ORM\OneToOne(targetEntity: StandardContact::class, mappedBy: 'address')] | ||
protected Contact|null $contact = null; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
need to fix this, to mimic how it is done with orm v3