EasyAdminBundle icon indicating copy to clipboard operation
EasyAdminBundle copied to clipboard

Not possible to give AssociationField an alternative getter?

Open ciaranmcnulty opened this issue 8 months ago • 3 comments

Describe the bug

I have an entity with a 'broken' getter, which for legacy reasons I can't safely change the signature of.

  1. I've not been able to see a way to get AssociationField to use an alternative getter for this field
  2. The error message is not clear, so some error checking may be missing

Example entity:

#[Entity]
#[Table(name: 'users')]
final readonly class User
{
    #[Id]
    #[Column(type: Types::INTEGER)]
    #[GeneratedValue]
    public int $id;

    #[Column(length: 100)]
    public string $name;

    #[ManyToOne]
    private ?User $parent;

    /** Existing accessor relied on by legacy system */
    public function getParent() : User|false
    {
        return $this->parent ?? false;
    }

    /** Accessor added to allow EasyAdminBundle to access the real data */
    public function getAdminParent() : ?User
    {
        return $this->parent;
    }
}

I try to set the form to use the alternative getter:

        yield AssociationField::new('parent')
            ->setFormTypeOption('getter', 'getAdminParent');

But as soon as I navigate to the /new page I get an exception:

TypeError:
Cannot use "::class" on false

  at vendor/easycorp/easyadmin-bundle/src/Factory/EntityFactory.php:119
  at EasyCorp\Bundle\EasyAdminBundle\Factory\EntityFactory->doCreate(null, null, null, false)
     (vendor/easycorp/easyadmin-bundle/src/Factory/EntityFactory.php:75)
  at EasyCorp\Bundle\EasyAdminBundle\Factory\EntityFactory->createForEntityInstance(false)
     (vendor/easycorp/easyadmin-bundle/src/Field/Configurator/AssociationConfigurator.php:200)
  at EasyCorp\Bundle\EasyAdminBundle\Field\Configurator\AssociationConfigurator->configureToOneAssociation(object(FieldDto))
     (vendor/easycorp/easyadmin-bundle/src/Field/Configurator/AssociationConfigurator.php:138)
  at EasyCorp\Bundle\EasyAdminBundle\Field\Configurator\AssociationConfigurator->configure(object(FieldDto), object(EntityDto), object(AdminContext))
     (vendor/easycorp/easyadmin-bundle/src/Factory/FieldFactory.php:102)
  at EasyCorp\Bundle\EasyAdminBundle\Factory\FieldFactory->processFields(object(EntityDto), object(FieldCollection))
     (vendor/easycorp/easyadmin-bundle/src/Factory/EntityFactory.php:43)
  at EasyCorp\Bundle\EasyAdminBundle\Factory\EntityFactory->processFields(object(EntityDto), object(FieldCollection))
     (vendor/easycorp/easyadmin-bundle/src/Controller/AbstractCrudController.php:301)
  at EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController->new(object(AdminContext))
     (vendor/symfony/http-kernel/HttpKernel.php:183)
  at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), 1)
     (vendor/symfony/http-kernel/HttpKernel.php:76)
  at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true)
     (vendor/symfony/http-kernel/Kernel.php:182)
  at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
     (vendor/symfony/runtime/Runner/Symfony/HttpKernelRunner.php:35)
  at Symfony\Component\Runtime\Runner\Symfony\HttpKernelRunner->run()
     (vendor/autoload_runtime.php:29)
  at require_once('/Users/ciaranmcnulty/Code/easyadmin-reproducer/vendor/autoload_runtime.php')
     (public/index.php:5)                

To Reproduce Repository here

Boot up and navigate to /admin/user/new

ciaranmcnulty avatar Apr 04 '25 16:04 ciaranmcnulty

I think you can do this : yield AssociationField::new('adminParent'); but you also need to create a setter

Or Maybe

yield AssociationField::new('adminParent')
    ->setProperty('parent');

dwd-akira avatar Apr 05 '25 16:04 dwd-akira

@dwd-akira Unfortunately your suggestion doesn't work, it still leads to an attempt to read the parent field via propertyaccess, which then uses the getParent method without out any way I can see to override it

(your suggested syntax would make sense!)

ciaranmcnulty avatar Apr 08 '25 09:04 ciaranmcnulty

And if you create a fake property

#[ManyToOne]
    private ?User $parent;

private ?User $adminParent;
yield AssociationField::new('adminParent')
    ->setProperty('adminParent');

dwd-akira avatar Apr 08 '25 13:04 dwd-akira