EasyCorp / EasyAdminBundle

EasyAdmin is a fast, beautiful and modern admin generator for Symfony applications.
MIT License
4.09k stars 1.02k forks source link

Allow entity access on configure methods (except for index) #3424

Open soullivaneuh opened 4 years ago

soullivaneuh commented 4 years ago

Short description of what this feature will allow to do:

Add the possibility to access the current entity instance related to the details or form CRUD action from the configure* methods.

This might be useful to configure the fields according to the current entity state.

Example of how to use this feature

In a nutshell something "like" this:

public function configureFields(string $pageName): iterable
{
    $entity = $this->getEntityInstance();
    // ...
}

Or maybe a more conventional way, this is to express the idea.

The current equivalent with Sonata admin would be like this (on an Admin class):

protected function configureShowFields(ShowMapper $show): void
{
    $entity = $this->getSubject();
}

I found we can get it from the context, but it's a private property so I can't do anything with this.

javiereguiluz commented 4 years ago

In many methods of the bundle we pass both the EntityDto and the AdminContext ... so we could do the same here. Let me think if there are some drawbacks of doing that.

lukasluecke commented 4 years ago

If we just pass the EntityDto ($context->getEntity), this would work for all views. We could just pass this as second parameter to configureFields and then FieldFactory::getDefaultFields could also use this, instead of needing to get it from the context directly. However this would mean that we would have to change the signature of this method, which would break a lot of things.. so maybe having a helper method instead is the easier way forward for now 🤔

For anyone that needs this in the meantime:

$this->get(AdminContextProvider::class)->getContext()->getEntity()->getInstance()
a-r-m-i-n commented 3 years ago

Hey. I've found a work-around, but I'm not happy with the current implementation, maybe you've got a hint.

I've created an EasyAdminSubscriber providing a listener for BeforeCrudActionEvent. There I can access $event->getAdminContext()->getEntity()->getInstance() and check the attributes which are relevant.

To pass the information to CrudController's configureFields() I've simply set a global variable in the event listener, like this:

$GLOBALS['eab_crud_product_has_prices'] = true

Now, I can conditionally add fields, if this global variable is true:

use EasyCorp\Bundle\EasyAdminBundle\Field\Field;

if (isset($GLOBALS['eab_crud_product_has_prices']) && $GLOBALS['eab_crud_product_has_prices']) {
    yield Field::new('prices', 'My conditionally visible prices');
}

Is there a more elegant way existing, to pass the information from event listener to CRUD controller?

bastien70 commented 2 years ago

Hello, what's about this feature at this moment ?

theghostlab commented 1 year ago

The following worked for me. Inside your crud controller, inject the entity repository:

public function __construct(private <EntityRepository> $repository){}

Then in the configureFields method:

        if( Crud::PAGE_EDIT === $pageName ) {

            $entityId = $this->getContext()->getRequest()->query->get('entityId');

            $entity = $this->repository->findOneBy(['id' => $entityId]);

        }

I hope that helps.

rafaelmartinelli commented 1 year ago

Currently it's possible to get the instance doing:

$entity = $this->getContext()->getEntity()->getInstance();

I think this is better than the former options.

HapiCZ commented 5 months ago

Currently it's possible to get the instance doing:

$entity = $this->getContext()->getEntity()->getInstance();

I think this is better than the former options.

This does not work if the CrudController is used in a CollectionField in another controller. Example: I have a GarageCrudController and in it a CollectionField referring to the CarCrudController. If I go to the action in the GarageCrudController, then the CarCrudController has a Garage entity instead of a Car.

jmariller commented 2 months ago

Currently it's possible to get the instance doing: $entity = $this->getContext()->getEntity()->getInstance(); I think this is better than the former options.

This does not work if the CrudController is used in a CollectionField in another controller. Example: I have a GarageCrudController and in it a CollectionField referring to the CarCrudController. If I go to the action in the GarageCrudController, then the CarCrudController has a Garage entity instead of a Car.

Hi @javiereguiluz I am also facing the same problem as described by @HapiCZ, would you have any advise on how to access the actual entity when being used in a CollectionField?