Skip to content
Advertisement

Symfony Entites vs CollectionType

I have the following problem with Symfony. I made 3 entities: Customer, Cart, and CartItem. And what I want, is to display all the Products that are inside Cart (These are inside Cart Item), and to be able to change quantity on ever single one with some kind of form. The best way is to use CollectionType, but I get this error. Second thought I had, is that my entities are wrong?

The form's view data is expected to be a "AppEntityCart", but it is a "DoctrineORMPersistentCollection". You can avoid this error by setting the "data_class" option to null or by adding a view transformer that transforms "DoctrineORMPersistentCollection" to an instance of "AppEntityCart".

Cart Entity

#[ORMEntity(repositoryClass: CartRepository::class)]
class Cart
{
    #[ORMId]
    #[ORMGeneratedValue]
    #[ORMColumn(type: 'integer')]
    private $id;

    #[ORMManyToOne(targetEntity: User::class, inversedBy: 'carts')]
    private $customer;

    #[ORMOneToMany(mappedBy: 'cart', targetEntity: CartItem::class)]
    private $cartItems;

    public function __construct()
    {
        $this->cartItems = new ArrayCollection();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getCustomer(): ?User
    {
        return $this->customer;
    }

    public function setCustomer(?User $customer): self
    {
        $this->customer = $customer;

        return $this;
    }

    /**
     * @return Collection<int, CartItem>
     */
    public function getCartItems(): Collection
    {
        return $this->cartItems;
    }

    public function addCartItem(CartItem $cartItem): self
    {
        if (!$this->cartItems->contains($cartItem)) {
            $this->cartItems[] = $cartItem;
            $cartItem->setCart($this);
        }

        return $this;
    }

    public function removeCartItem(CartItem $cartItem): self
    {
        if ($this->cartItems->removeElement($cartItem)) {
            // set the owning side to null (unless already changed)
            if ($cartItem->getCart() === $this) {
                $cartItem->setCart(null);
            }
        }

        return $this;
    }

}

Cart Item Entity

<?php

#[ORMEntity(repositoryClass: CartItemRepository::class)]
class CartItem
{
    #[ORMId]
    #[ORMGeneratedValue]
    #[ORMColumn(type: 'integer')]
    private $id;

    /**
     * @AssertGreaterThanOrEqual(1)
     */
    #[ORMColumn(type: 'integer')]
    private $quantity;

    #[ORMManyToOne(targetEntity: Product::class, inversedBy: 'cartItems')]
    private $product;

    #[ORMManyToOne(targetEntity: Cart::class, inversedBy: 'cartItems')]
    private $cart;

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getQuantity(): ?int
    {
        return $this->quantity;
    }

    public function setQuantity(int $quantity): self
    {
        $this->quantity = $quantity;

        return $this;
    }

    public function getProduct(): ?Product
    {
        return $this->product;
    }

    public function setProduct(?Product $product): self
    {
        $this->product = $product;

        return $this;
    }

    public function getCart(): ?Cart
    {
        return $this->cart;
    }

    public function setCart(?Cart $cart): self
    {
        $this->cart = $cart;

        return $this;
    }



}

CartType

class CartType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('customer')
            ->add('cartitem', CollectionType::class, [
                'entry_type' => CartItemType::class,
                'entry_options' => ['label' => false]
            ]);
    }

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

CartItemType

<?php

class CartItemType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('quantity')
            ->add('product')
            ->add('cart')
        ;
    }

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

CartController

    #[Route('/', name: 'show_cart')]
    public function showCart(CartService $cartService, Request $request): Response
    {
        $cart = $cartService->getCartItem();
        $form = $this->createForm(CartType::class, $cart);


        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
           return $this->redirect($this->generateUrl('app_home'));
        }


        return $this->render('cart/index.html.twig', [
            'cart' => $cart,
            'form' => $form
        ]);
    }

Advertisement

Answer

From what I can see you have two errors in your code:

In CartType you have used cartitem instead of cartitems. Symfony tried to use getCartItem, which is no method at all.

The CartType should look like following:

class CartType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('customer')
            ->add('cartitems', CollectionType::class, [
                'entry_type' => CartItemType::class,
                'entry_options' => ['label' => false]
            ]);
    }

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

Also it seems like the data you throw into the form are no doctrine-entity matching the Cart-Entity. It seems like you give over an unparsed object to your form.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement