Search code examples
phpsymfonyeasyadmineasyadmin3

Symfony Easy Admin Bundle: Preload nested form data - Fails Entity of type ...must be managed


I'm trying to create a nested form for these three instances, where the inventory has default data, and the nested form InventoryProduct has all the Products in the database by default in the form.

  • Inventory (has one or more InventarioProduct) - Id, StartDate, EndDate
  • InventoryProduct - Id, Product, Units, RejectedUnits, QuarantineUnits
  • Product - Id, Name, Inci, some other data from product

So we add to InventoryCrudCrontroller the createEntityMethod:

public function createEntity(string $entityFqcn)
    {
        $inventory= new Inventory();
        $inventory->setStartDate(new DateTime('now'));
        $inventory->setEndDate(null);

        $productRepository= $this->entityManager->getRepository(MateriaPrima::class);

        $products= $productRepository->findAll();

        foreach ($products as $product) {
            $inventoryProduct= new InventoryProduct();
            $inventoryProduct->setProduct($product);
            $inventoryProduct->setUnits(0);
            $inventoryProduct->setUnitsRejected(0);
            $inventoryProduct->setUnitsQuarantine(0);
            $inventoryProduct->setInventory($inventory);

            $inventory->addInventarioProduct($inventoryProduct);
        }

And on the configureFields method on InventoryCrudCrontroller:

public function configureFields(string $pageName): iterable
    {

        if (Crud::PAGE_EDIT === $pageName || Crud::PAGE_NEW == $pageName) {
            return [
                DateTimeField::new('startDate')
                    ->setColumns(6)
                    ->setValue(new DateTime()),
                DateTimeField::new('endDate')
                    ->setColumns(6),
                CollectionField::new('products', 'Products:')
                    ->onlyOnForms()
                    ->allowAdd()
                    ->allowDelete()
                    ->setEntryIsComplex(false)
                    ->setEntryType(InventoryProductType::class)
                    ->renderExpanded(true)
                    ->setFormTypeOptions(
                        [
                            'by_reference' => false,
                        ]
                    )
                    ->setColumns(12),

And we add the class InventoryProductType for the customs form:

class InventoryProducts extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {

        $builder
            ->add(
                'product',
                EntityType::class,
                ['class' => Product::class, 'label' => '-']
            )
            ->add('units')
            ->add('unitsRejected')
            ->add('unitsQuarantine')
            ;
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => InventoryProduct::class,
        ]);
    }
}


When we try to add another registry, we got:

Entity of type "App\Entity\Inventory" passed to the choice field must be managed. Maybe you forget to persist it in the entity manager?

What am I doing wrong?

Thanks for your help!!


Solution

  • The error tell you that you are using an entity of type App\Entity\Inventory which is not managed by the entity manager.

    If you look into your code, you are creating a new entity in your createEntity method, but never persisted it.

    You could either persist it in your method like:

    public function createEntity(string $entityFqcn)
        {
            $inventory= new Inventory();
            $inventory->setStartDate(new DateTime('now'));
            $inventory->setEndDate(null);
            $this->entityManager->persist($inventory);
    
            $productRepository= $this->entityManager->getRepository(MateriaPrima::class);
    
            $products= $productRepository->findAll();
            
            foreach ($products as $product) {
                $inventoryProduct= new InventoryProduct();
                $inventoryProduct->setProduct($product);
                $inventoryProduct->setUnits(0);
                $inventoryProduct->setUnitsRejected(0);
                $inventoryProduct->setUnitsQuarantine(0);
                $inventoryProduct->setInventory($inventory);
                $this->entityManager->persist($inventoryProduct);
    
                $inventory->addInventarioProduct($inventoryProduct);
            }
        }
    

    Or add cascading persist on your entity.