diff --git a/src/Maker/MakeEntity.php b/src/Maker/MakeEntity.php
index 71bfd3b2f..4dfdcb176 100644
--- a/src/Maker/MakeEntity.php
+++ b/src/Maker/MakeEntity.php
@@ -235,12 +235,6 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen
// save the inverse side if it's being mapped
if ($newField->getMapInverseRelation()) {
$fileManagerOperations[$otherManipulatorFilename] = $otherManipulator;
- } else {
- // print message about it not being saved
- $fileManagerOperations[] = sprintf(
- 'The inverse side of the relation was not mapped in "%s" because it lives in the vendor/ directory.',
- $newField->getInverseClass()
- );
}
$currentFields[] = $newFieldName;
} else {
@@ -554,8 +548,30 @@ function ($name) use ($targetClass) {
return $io->confirm(sprintf('Do you want to automatically delete orphaned %s objects (orphanRemoval)?', $owningClass), false);
};
- $setMapInverseSide = function (EntityRelation $relation) {
- $relation->setMapInverseRelation(!$this->isClassInVendor($relation->getInverseClass()));
+ $askInverseSide = function (EntityRelation $relation) use ($io) {
+ if ($this->isClassInVendor($relation->getInverseClass())) {
+ $relation->setMapInverseRelation(false);
+ }
+
+ // recommend an inverse side, except for OneToOne, where it's inefficient
+ $recommendMappingInverse = EntityRelation::ONE_TO_ONE === $relation->getType() ? false : true;
+
+ $getterMethodName = 'get'.Str::asCamelCase(Str::getShortClassName($relation->getOwningClass()));
+ if (EntityRelation::ONE_TO_ONE !== $relation->getType()) {
+ // pluralize!
+ $getterMethodName = Str::singularCamelCaseToPluralCamelCase($getterMethodName);
+ }
+ $mapInverse = $io->confirm(
+ sprintf(
+ 'Do you want to add a new property to %s so that you can access/update %s objects from it - e.g. $%s->%s()?',
+ Str::getShortClassName($relation->getInverseClass()),
+ Str::getShortClassName($relation->getOwningClass()),
+ Str::asLowerCamelCase(Str::getShortClassName($relation->getInverseClass())),
+ $getterMethodName
+ ),
+ $recommendMappingInverse
+ );
+ $relation->setMapInverseRelation($mapInverse);
};
switch ($type) {
@@ -572,7 +588,7 @@ function ($name) use ($targetClass) {
$relation->getOwningClass()
));
- $setMapInverseSide($relation);
+ $askInverseSide($relation);
if ($relation->getMapInverseRelation()) {
$io->comment(sprintf(
'A new property will also be added to the %s class so that you can access the related %s objects from it.',
@@ -583,13 +599,14 @@ function ($name) use ($targetClass) {
$relation->getInverseClass(),
Str::singularCamelCaseToPluralCamelCase(Str::getShortClassName($relation->getOwningClass()))
));
- }
- if (!$relation->isNullable()) {
- $relation->setOrphanRemoval($askOrphanRemoval(
- $relation->getOwningClass(),
- $relation->getInverseClass()
- ));
+ // orphan removal only applies of the inverse relation is set
+ if (!$relation->isNullable()) {
+ $relation->setOrphanRemoval($askOrphanRemoval(
+ $relation->getOwningClass(),
+ $relation->getInverseClass()
+ ));
+ }
}
break;
@@ -633,7 +650,7 @@ function ($name) use ($targetClass) {
);
$relation->setOwningProperty($newFieldName);
- $setMapInverseSide($relation);
+ $askInverseSide($relation);
if ($relation->getMapInverseRelation()) {
$io->comment(sprintf(
'A new property will also be added to the %s class so that you can access the related %s objects from it.',
@@ -660,7 +677,7 @@ function ($name) use ($targetClass) {
$relation->getOwningClass()
));
- $setMapInverseSide($relation);
+ $askInverseSide($relation);
if ($relation->getMapInverseRelation()) {
$io->comment(sprintf(
'A new property will also be added to the %s class so that you can access the related %s object from it.',
diff --git a/tests/Maker/FunctionalTest.php b/tests/Maker/FunctionalTest.php
index 119431381..ec02275ff 100644
--- a/tests/Maker/FunctionalTest.php
+++ b/tests/Maker/FunctionalTest.php
@@ -206,6 +206,8 @@ public function getCommandTests()
'ManyToOne',
// nullable
'n',
+ // do you want to generate an inverse relation? (default to yes)
+ '',
// field name on opposite side - use default 'userAvatarPhotos'
'',
// orphanRemoval (default to no)
@@ -218,6 +220,31 @@ public function getCommandTests()
->updateSchemaAfterCommand()
];
+ yield 'entity_many_to_one_simple_no_inverse' => [MakerTestDetails::createTest(
+ $this->getMakerInstance(MakeEntity::class),
+ [
+ // entity class name
+ 'UserAvatarPhoto',
+ // field name
+ 'user',
+ // add a relationship field
+ 'relation',
+ // the target entity
+ 'User',
+ // relation type
+ 'ManyToOne',
+ // nullable
+ 'n',
+ // do you want to generate an inverse relation? (default to yes)
+ 'n',
+ // finish adding fields
+ ''
+ ])
+ ->setFixtureFilesPath(__DIR__.'/../fixtures/MakeEntityManyToOneNoInverse')
+ ->configureDatabase()
+ ->updateSchemaAfterCommand()
+ ];
+
yield 'entity_one_to_many_simple' => [MakerTestDetails::createTest(
$this->getMakerInstance(MakeEntity::class),
[
@@ -231,6 +258,8 @@ public function getCommandTests()
'UserAvatarPhoto',
// relation type
'OneToMany',
+ // inverse side?
+ 'y',
// field name on opposite side - use default 'user'
'',
// nullable
@@ -258,6 +287,8 @@ public function getCommandTests()
'User',
// relation type
'ManyToMany',
+ // inverse side?
+ 'y',
// field name on opposite side - use default 'courses'
'',
// finish adding fields
@@ -283,6 +314,8 @@ public function getCommandTests()
'OneToOne',
// nullable
'n',
+ // inverse side?
+ 'y',
// field name on opposite side - use default 'userProfile'
'',
// finish adding fields
@@ -310,8 +343,6 @@ public function getCommandTests()
* normally, we ask for the field on the *other* side, but we
* do not here, since the other side won't be mapped.
*/
- // orphanRemoval (default to no)
- '',
// finish adding fields
''
])
diff --git a/tests/fixtures/MakeEntityManyToOneNoInverse/src/Entity/User.php b/tests/fixtures/MakeEntityManyToOneNoInverse/src/Entity/User.php
new file mode 100644
index 000000000..773668263
--- /dev/null
+++ b/tests/fixtures/MakeEntityManyToOneNoInverse/src/Entity/User.php
@@ -0,0 +1,23 @@
+id;
+ }
+}
diff --git a/tests/fixtures/MakeEntityManyToOneNoInverse/tests/GeneratedEntityTest.php b/tests/fixtures/MakeEntityManyToOneNoInverse/tests/GeneratedEntityTest.php
new file mode 100644
index 000000000..6fe3f832a
--- /dev/null
+++ b/tests/fixtures/MakeEntityManyToOneNoInverse/tests/GeneratedEntityTest.php
@@ -0,0 +1,36 @@
+getContainer()
+ ->get('doctrine')
+ ->getManager();
+
+ $em->createQuery('DELETE FROM App\\Entity\\User u')->execute();
+ $em->createQuery('DELETE FROM App\\Entity\\UserAvatarPhoto u')->execute();
+
+ $user = new User();
+ $em->persist($user);
+
+ $photo = new UserAvatarPhoto();
+ $photo->setUser($user);
+ $em->persist($photo);
+
+ $em->flush();
+ $em->refresh($photo);
+
+ $this->assertSame($photo->getUser(), $user);
+ }
+}