Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@
->arg(2, service('request_stack'))
->arg(3, service(ControllerFactory::class))
->arg(4, new Reference(FieldFactory::class))
->arg(5, service(EntityRepository::class))
Copy link
Copy Markdown
Contributor

@Seb33300 Seb33300 May 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @KDederichs,

Instead of adding this dependency to many field configurators (I saw you also created a similar PR for the CollectionConfigurator, and I also did the same with EntityConfigurator in my PR), maybe we can move it to the CommonPreConfigurator, so we resolve the field association once for all field configurators and avoid code duplication?

Also, this may no longer be needed:

$doctrineMetadata = [];
if (isset($entityDto->getClassMetadata()->fieldMappings[$field->getProperty()])) {
$doctrineMetadata = (array) $entityDto->getClassMetadata()->getFieldMapping($field->getProperty());
} elseif ($entityDto->getClassMetadata()->hasAssociation($field->getProperty())) {
$mappingType = $entityDto->getClassMetadata()->getAssociationMapping($field->getProperty())['type'];
$doctrineMetadata = (array) $entityDto->getClassMetadata()->getAssociationMapping($field->getProperty());
$doctrineMetadata['type'] = $mappingType;
}
$field->setDoctrineMetadata($doctrineMetadata);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be a better solution to solidify it in one place when possible yeah.
Tbh I just needed it in that moment in my backend so I fixed the issue where it popped up as I implemented the things I needed (and applied them to production via Patch files).

If you want you can extend your PR with a general solution, since both of mine are dependent on your PR anyways.


->set(AvatarConfigurator::class)

Expand Down
9 changes: 8 additions & 1 deletion src/Field/Configurator/AssociationConfigurator.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
use EasyCorp\Bundle\EasyAdminBundle\Form\Type\CrudAutocompleteType;
use EasyCorp\Bundle\EasyAdminBundle\Form\Type\CrudFormType;
use EasyCorp\Bundle\EasyAdminBundle\Orm\EntityRepository as EAEntityRepository;
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGeneratorInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException;
Expand All @@ -38,6 +39,7 @@ public function __construct(
private RequestStack $requestStack,
private ControllerFactory $controllerFactory,
private FieldFactory $fieldFactory,
private EAEntityRepository $entityRepository,
) {
}

Expand All @@ -49,14 +51,19 @@ public function supports(FieldDto $field, EntityDto $entityDto): bool
public function configure(FieldDto $field, EntityDto $entityDto, AdminContext $context): void
{
$propertyName = $field->getProperty();
$resolvedProperty = $this->entityRepository->resolveNestedAssociations(null, $entityDto, $propertyName, true);
/** @var EntityDto $entityDtoResolved */
$entityDtoResolved = $resolvedProperty['entity_dto'];
/** @var string $resolvedProperty */
$resolvedProperty = $resolvedProperty['property_name'];

if (!$this->isAssociation($entityDto->getClassMetadata(), $propertyName)) {
throw new \RuntimeException(sprintf('The "%s" field is not a Doctrine association, so it cannot be used as an association field.', $propertyName));
}

// the target CRUD controller can be NULL; in that case, field value doesn't link to the related entity
$targetCrudControllerFqcn = $field->getCustomOption(AssociationField::OPTION_EMBEDDED_CRUD_FORM_CONTROLLER)
?? $context->getAdminControllers()->findCrudControllerByEntity($entityDto->getClassMetadata()->getAssociationTargetClass($propertyName));
?? $context->getAdminControllers()->findCrudControllerByEntity($entityDtoResolved->getClassMetadata()->getAssociationTargetClass($resolvedProperty));

if (true === $field->getCustomOption(AssociationField::OPTION_RENDER_AS_EMBEDDED_FORM)) {
if (false === $entityDto->getClassMetadata()->isSingleValuedAssociation($propertyName)) {
Expand Down
Loading