From d10e50cd3f3f6d778a36cd507e69172e540dd5ea Mon Sep 17 00:00:00 2001 From: ramity Date: Sun, 7 Jan 2024 08:41:53 +0000 Subject: [PATCH 1/6] Added a prompt if the user would like to specify a joinTable name during the creation of a many-to-many relation. --- src/Doctrine/BaseRelation.php | 6 ++++++ src/Doctrine/EntityRelation.php | 12 ++++++++++++ src/Maker/MakeEntity.php | 16 ++++++++++++++++ src/Util/ClassSourceManipulator.php | 6 ++++++ 4 files changed, 40 insertions(+) diff --git a/src/Doctrine/BaseRelation.php b/src/Doctrine/BaseRelation.php index 5ab9a513f..702aa1e19 100644 --- a/src/Doctrine/BaseRelation.php +++ b/src/Doctrine/BaseRelation.php @@ -28,6 +28,7 @@ public function __construct( private bool $isOwning = false, private bool $orphanRemoval = false, private bool $isNullable = false, + private ?string $joinTableName = null, ) { } @@ -85,4 +86,9 @@ public function isNullable(): bool { return $this->isNullable; } + + public function getJoinTableName(): ?string + { + return $this->joinTableName; + } } diff --git a/src/Doctrine/EntityRelation.php b/src/Doctrine/EntityRelation.php index db41f8052..abb35aa36 100644 --- a/src/Doctrine/EntityRelation.php +++ b/src/Doctrine/EntityRelation.php @@ -27,6 +27,7 @@ final class EntityRelation private bool $isSelfReferencing = false; private bool $orphanRemoval = false; private bool $mapInverseRelation = true; + private $joinTableName; public function __construct( private string $type, @@ -97,6 +98,7 @@ public function getOwningRelation(): RelationManyToMany|RelationOneToOne|Relatio isSelfReferencing: $this->isSelfReferencing, mapInverseRelation: $this->mapInverseRelation, isOwning: true, + joinTableName: $this->joinTableName, )), self::ONE_TO_ONE => (new RelationOneToOne( propertyName: $this->owningProperty, @@ -186,4 +188,14 @@ public function setMapInverseRelation(bool $mapInverseRelation): void $this->mapInverseRelation = $mapInverseRelation; } + + public function getJoinTableName(): ?string + { + return $this->joinTableName; + } + + public function setJoinTableName(?string $joinTableName) + { + $this->joinTableName = $joinTableName; + } } diff --git a/src/Maker/MakeEntity.php b/src/Maker/MakeEntity.php index 07896c675..608af493a 100644 --- a/src/Maker/MakeEntity.php +++ b/src/Maker/MakeEntity.php @@ -619,6 +619,20 @@ function ($name) use ($targetClass) { $relation->setMapInverseRelation($mapInverse); }; + $askJoinTableName = function (EntityRelation $relation) use ($io) { + $joinTableDecision = $io->confirm( + 'Do you want to specify a join table? You may want to do this if you plan on having multiple many-to-many relations to the same entity.', + false + ); + + if ($joinTableDecision) { + $relation->setJoinTableName($io->ask( + 'What should the join table be named?', + lcfirst(Str::getShortClassName($relation->getOwningClass())) . ucfirst($relation->getOwningProperty()) + )); + } + }; + switch ($type) { case EntityRelation::MANY_TO_ONE: $relation = new EntityRelation( @@ -708,6 +722,8 @@ function ($name) use ($targetClass) { )); } + $askJoinTableName($relation); + break; case EntityRelation::ONE_TO_ONE: $relation = new EntityRelation( diff --git a/src/Util/ClassSourceManipulator.php b/src/Util/ClassSourceManipulator.php index 6a9d86d93..200491b36 100644 --- a/src/Util/ClassSourceManipulator.php +++ b/src/Util/ClassSourceManipulator.php @@ -18,6 +18,7 @@ use Doctrine\ORM\Mapping\Embedded; use Doctrine\ORM\Mapping\JoinColumn; use Doctrine\ORM\Mapping\ManyToMany; +use Doctrine\ORM\Mapping\JoinTable; use Doctrine\ORM\Mapping\ManyToOne; use Doctrine\ORM\Mapping\OneToMany; use Doctrine\ORM\Mapping\OneToOne; @@ -558,6 +559,11 @@ private function addCollectionRelation(BaseCollectionRelation $relation): void ), ]; + // Conditionally add joinTable attribute + if ($relation->getJoinTableName()) { + $attributes[] = $this->buildAttributeNode(JoinTable::class, ['name' => $relation->getJoinTableName()], 'ORM'); + } + $this->addProperty( name: $relation->getPropertyName(), attributes: $attributes, From 309bf05781fb473791279d69c61eef7b7ea0eeb1 Mon Sep 17 00:00:00 2001 From: ramity Date: Sun, 7 Jan 2024 10:14:45 +0000 Subject: [PATCH 2/6] fixed the two php-cs-fixer errors --- src/Maker/MakeEntity.php | 2 +- src/Util/ClassSourceManipulator.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Maker/MakeEntity.php b/src/Maker/MakeEntity.php index 608af493a..b67a868ba 100644 --- a/src/Maker/MakeEntity.php +++ b/src/Maker/MakeEntity.php @@ -628,7 +628,7 @@ function ($name) use ($targetClass) { if ($joinTableDecision) { $relation->setJoinTableName($io->ask( 'What should the join table be named?', - lcfirst(Str::getShortClassName($relation->getOwningClass())) . ucfirst($relation->getOwningProperty()) + lcfirst(Str::getShortClassName($relation->getOwningClass())).ucfirst($relation->getOwningProperty()) )); } }; diff --git a/src/Util/ClassSourceManipulator.php b/src/Util/ClassSourceManipulator.php index 200491b36..6d95cdeed 100644 --- a/src/Util/ClassSourceManipulator.php +++ b/src/Util/ClassSourceManipulator.php @@ -17,8 +17,8 @@ use Doctrine\ORM\Mapping\Column; use Doctrine\ORM\Mapping\Embedded; use Doctrine\ORM\Mapping\JoinColumn; -use Doctrine\ORM\Mapping\ManyToMany; use Doctrine\ORM\Mapping\JoinTable; +use Doctrine\ORM\Mapping\ManyToMany; use Doctrine\ORM\Mapping\ManyToOne; use Doctrine\ORM\Mapping\OneToMany; use Doctrine\ORM\Mapping\OneToOne; From 17b939df853bfca6f49816a754c8620e65a77f62 Mon Sep 17 00:00:00 2001 From: ramity Date: Sun, 7 Jan 2024 10:29:42 +0000 Subject: [PATCH 3/6] fixed 3 places where ManyToMany relations were being tested --- tests/Maker/MakeEntityTest.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/Maker/MakeEntityTest.php b/tests/Maker/MakeEntityTest.php index 6e8d36f82..73827ff59 100644 --- a/tests/Maker/MakeEntityTest.php +++ b/tests/Maker/MakeEntityTest.php @@ -239,6 +239,8 @@ public function getTestDetails(): \Generator 'y', // field name on opposite side - use default 'courses' '', + // skip join table + '', // finish adding fields '', ]); @@ -272,6 +274,8 @@ public function getTestDetails(): \Generator 'y', // field name on opposite side - use default 'courses' '', + // skip join table + '', // finish adding fields '', ]); @@ -363,6 +367,8 @@ public function getTestDetails(): \Generator * normally, we ask for the field on the *other* side, but we * do not here, since the other side won't be mapped. */ + // skip join table + '', // finish adding fields '', ]); From 5abc8c21e1f691d6f2b2b6d7665e5c09d015d4c8 Mon Sep 17 00:00:00 2001 From: ramity Date: Sun, 7 Jan 2024 18:31:03 +0000 Subject: [PATCH 4/6] updated tests comments to match others, added testcase for custom join table --- tests/Maker/MakeEntityTest.php | 37 +++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/tests/Maker/MakeEntityTest.php b/tests/Maker/MakeEntityTest.php index 73827ff59..a7715b3a0 100644 --- a/tests/Maker/MakeEntityTest.php +++ b/tests/Maker/MakeEntityTest.php @@ -239,7 +239,7 @@ public function getTestDetails(): \Generator 'y', // field name on opposite side - use default 'courses' '', - // skip join table + // join table? - use default 'n' '', // finish adding fields '', @@ -274,7 +274,7 @@ public function getTestDetails(): \Generator 'y', // field name on opposite side - use default 'courses' '', - // skip join table + // join table? - use default 'n' '', // finish adding fields '', @@ -284,6 +284,37 @@ public function getTestDetails(): \Generator }), ]; + yield 'it_adds_many_to_many_with_custom_join_table' => [$this->createMakeEntityTest() + ->run(function (MakerTestRunner $runner) { + $this->copyEntity($runner, 'User-basic.php'); + + $runner->runMaker([ + // entity class name + 'Course', + // field name + 'students', + // add a relationship field + 'relation', + // the target entity + 'User', + // relation type + 'ManyToMany', + // inverse side? + 'y', + // field name on opposite side - use default 'courses' + '', + // join table? + 'y', + // join table name - use default 'courseStudents' + '', + // finish adding fields + '', + ]); + + $this->runCustomTest($runner, 'it_adds_many_to_many_simple.php'); + }), + ]; + yield 'it_adds_one_to_one_simple' => [$this->createMakeEntityTest() ->run(function (MakerTestRunner $runner) { $this->copyEntity($runner, 'User-basic.php'); @@ -367,7 +398,7 @@ public function getTestDetails(): \Generator * normally, we ask for the field on the *other* side, but we * do not here, since the other side won't be mapped. */ - // skip join table + // join table? - use default 'n' '', // finish adding fields '', From f4eda5a0b36124e57b00c2eb5d5c22946b01a496 Mon Sep 17 00:00:00 2001 From: ramity Date: Sun, 7 Jan 2024 18:33:03 +0000 Subject: [PATCH 5/6] fixed test name + added suggested change to add type to EntityRelation::joinTableName --- src/Doctrine/EntityRelation.php | 2 +- tests/Maker/MakeEntityTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Doctrine/EntityRelation.php b/src/Doctrine/EntityRelation.php index abb35aa36..adb3546d8 100644 --- a/src/Doctrine/EntityRelation.php +++ b/src/Doctrine/EntityRelation.php @@ -27,7 +27,7 @@ final class EntityRelation private bool $isSelfReferencing = false; private bool $orphanRemoval = false; private bool $mapInverseRelation = true; - private $joinTableName; + private ?string $joinTableName; public function __construct( private string $type, diff --git a/tests/Maker/MakeEntityTest.php b/tests/Maker/MakeEntityTest.php index a7715b3a0..b1392a90c 100644 --- a/tests/Maker/MakeEntityTest.php +++ b/tests/Maker/MakeEntityTest.php @@ -311,7 +311,7 @@ public function getTestDetails(): \Generator '', ]); - $this->runCustomTest($runner, 'it_adds_many_to_many_simple.php'); + $this->runCustomTest($runner, 'it_adds_many_to_many_with_custom_join_table.php'); }), ]; From b5b7ccffd453c4c50c7860b5b352740dab9e307f Mon Sep 17 00:00:00 2001 From: ramity Date: Mon, 8 Jan 2024 06:52:12 +0000 Subject: [PATCH 6/6] initialized value to null to avoid errors from uninit access --- src/Doctrine/EntityRelation.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Doctrine/EntityRelation.php b/src/Doctrine/EntityRelation.php index adb3546d8..91db3effc 100644 --- a/src/Doctrine/EntityRelation.php +++ b/src/Doctrine/EntityRelation.php @@ -27,7 +27,7 @@ final class EntityRelation private bool $isSelfReferencing = false; private bool $orphanRemoval = false; private bool $mapInverseRelation = true; - private ?string $joinTableName; + private ?string $joinTableName = null; public function __construct( private string $type,