DEV Community

Cover image for Clearing the Cart | Building a Shopping Cart with Symfony
Quentin Ferrer
Quentin Ferrer

Posted on

Clearing the Cart | Building a Shopping Cart with Symfony

In the same way as the Remove button of the cart, we will use the form events to manage the Clear button of the cart.

Creating the Event Subscriber

Create a ClearCartListener subscriber and subscribe to the FormEvents::POST_SUBMIT event:

<?php

namespace App\Form\EventListener;

use App\Entity\Order;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;

class ClearCartListener implements EventSubscriberInterface
{
    /**
     * @inheritDoc
     */
    public static function getSubscribedEvents(): array
    {
        return [FormEvents::POST_SUBMIT => 'postSubmit'];
    }

    /**
     * Removes all items from the cart when the clear button is clicked.
     *
     * @param FormEvent $event
     */
    public function postSubmit(FormEvent $event): void
    {
        $form = $event->getForm();
        $cart = $form->getData();

        if (!$cart instanceof Order) {
            return;
        }

        // Is the clear button clicked?
        if (!$form->get('clear')->isClicked()) {
            return;
        }

        // Clears the cart
        $cart->removeItems();
    }
}
Enter fullscreen mode Exit fullscreen mode

The current cart is available from the main form by using the FormEvent::getData() method. It should be an instance of an Order entity.

If the Clear button has been clicked, we remove all items from the cart. In other words, we clear the cart.

Registering the Event Subscriber

To register the CleartCartListener subscriber to the CartType form, use the addEventListener method using the form builder:

<?php

namespace App\Form;

use App\Entity\Order;
use App\Form\EventListener\ClearCartListener;
use App\Form\EventListener\RemoveItemListener;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class CartType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('items', CollectionType::class, [
                'entry_type' => CartItemType::class
            ])
            ->add('save', SubmitType::class)
            ->add('clear', SubmitType::class);

        $builder->addEventSubscriber(new RemoveItemListener());
        $builder->addEventSubscriber(new ClearCartListener());
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Order::class,
        ]);
    }
}
Enter fullscreen mode Exit fullscreen mode

Of course, you can merge the two listeners into one but the goal was to show you how to use the form events to dynamically modify form data.

At this point, we have managed all the cart features, but there is still some work to be done. Let's go to the next step, it's almost done.

Top comments (2)

Collapse
 
sc8 profile image
SC

Hello, how to combine these two lines into one? I tried few ways but it doesn't works...

$builder->addEventSubscriber(new RemoveCartItemListener());
$builder->addEventSubscriber(new ClearCartListener());

Collapse
 
qferrer profile image
Quentin Ferrer

Hello. You can't. The FormConfigBuilderInterface does not allow you to add multiple subscribers at once. So you have no choice to use addEventSubscriber for each listener you want to attach to the form.