3

I'm using the Sylius Cart and Order Bundles and trying to add an item to the cart and show a summary of the items in the cart. The problem I'm having is Symfony/Sylius forgets that it has made a cart and added items to it.

If I click a link going to the add page for the sylius cart, generated by

{{ path('sylius_cart_item_add', {'productId': class.ClassID}) }}

No error occurs. If I look in the database I can see that a new entry has been created in the sylius_cart table and the sylius_cart_item table, with the correct information; however, the cart summary page shows nothing and thinks the cart is empty.

If I try to add another item, it creates another new cart and promptly forgets that it made the cart.

I have the following bundles loading in AppKernel.php

public function registerBundles()
{
        $bundles = array(
            //bundles for using the shopping cart
            new FOS\RestBundle\FOSRestBundle(),
            new JMS\SerializerBundle\JMSSerializerBundle($this),
            new Sylius\Bundle\ResourceBundle\SyliusResourceBundle(),
            new WhiteOctober\PagerfantaBundle\WhiteOctoberPagerfantaBundle(),
            new Sylius\Bundle\MoneyBundle\SyliusMoneyBundle(),
            new Sylius\Bundle\OrderBundle\SyliusOrderBundle(),
            new Sylius\Bundle\CartBundle\SyliusCartBundle(),
            new Sylius\Bundle\SequenceBundle\SyliusSequenceBundle(),


            //bundles for styling with bootstrap 3
            new Mopa\Bundle\BootstrapBundle\MopaBootstrapBundle(),

            //mssql connection library
            new Realestate\MssqlBundle\RealestateMssqlBundle(),

            //default frameworks
            new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
            new Symfony\Bundle\SecurityBundle\SecurityBundle(),
            new Symfony\Bundle\TwigBundle\TwigBundle(),
            new Symfony\Bundle\MonologBundle\MonologBundle(),
            new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
            new Symfony\Bundle\AsseticBundle\AsseticBundle(),
            new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
            new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
            new CE\CEBundle\CEBundle(),
        );

        if (in_array($this->getEnvironment(), array('dev', 'test'))) {
            $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
            $bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle();
            $bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle();
        }

        return $bundles;
}

My ItemResolver class looks like

namespace CE\CEBundle\Cart;

use Sylius\Component\Cart\Model\CartItemInterface;
use Sylius\Component\Cart\Resolver\ItemResolverInterface;
use Sylius\Component\Cart\Resolver\ItemResolvingException;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\ORM\EntityManager;

class ItemResolver implements ItemResolverInterface
{
    private $entityManager;

    public function __construct(EntityManager $entityManager)
    {
        $this->entityManager = $entityManager;
    }


    public function resolve(CartItemInterface $item, $data)
    {
        //grab the product ID
        $productId = $data->get('productId');


        if (!$productId || !$product = $this->getProductRepository()->find($productId)) {
            throw new ItemResolvingException('Requested product was not found');
        }

        $item->setProductId($product->getId());
        $item->setUnitPrice($product->getClassFee() * 100);

        return $item;
    }

    private function getProductRepository()
    {
        return $this->entityManager->getRepository('CEBundle:Product');
    }
}

My CartItem class looks like

namespace CE\CEBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Sylius\Component\Cart\Model\CartItem as BaseCartItem;

/**
 * @ORM\Entity
 * @ORM\Table(name="sylius_cart_item")
 */
class CartItem extends BaseCartItem
{
    /**
     * @ORM\Column(type="string", name="product_id", length=8)
     */
    private $productId;

    public function getProductId()
    {
        return $this->productId;
    }

    public function setProductId($Id)
    {
        $this->productId = $Id;
    }
}

I have the following config in my config.yml

imports:
    - { resource: parameters.yml }
    - { resource: security.yml }

framework:
    #esi:             ~
    #translator:      { fallback: "%locale%" }
    secret:          "%secret%"
    router:
        resource: "%kernel.root_dir%/config/routing.yml"
        strict_requirements: ~
    form: ~

    csrf_protection: ~
    validation:      { enable_annotations: true }
    templating:
        engines: ['twig']
        #assets_version: SomeVersionScheme
    default_locale:  "%locale%"
    trusted_hosts:   ~
    trusted_proxies: ~
    session:
        # handler_id set to null will use default session handler from php.ini
        handler_id:  ~
        name: SYLIUS_SESSION
        cookie_lifetime: 72000
    fragments:       ~
    http_method_override: true

# Twig Configuration
twig:
    debug:            "%kernel.debug%"
    strict_variables: "%kernel.debug%"

# Assetic Configuration
assetic:
    debug:          "%kernel.debug%"
    use_controller: false
    bundles:        [ ]
    #java: /usr/bin/java
    filters:
        cssrewrite: ~
        #closure:
        #    jar: "%kernel.root_dir%/Resources/java/compiler.jar"
        #yui_css:
        #    jar: "%kernel.root_dir%/Resources/java/yuicompressor-2.4.7.jar"

# Doctrine Configuration
doctrine:
    dbal:
        default_connection: default
        connections:
            default:
                driver:   "%database_driver%"
                host:     "%database_host%"
                port:     "%database_port%"
                dbname:   "%database_name%"
                user:     "%database_user%"
                password: "%database_password%"
                charset:  UTF8
            mssqlDB:
                driver_class:   Realestate\MssqlBundle\Driver\PDODblib\Driver
                host:     %db.other.host%
                dbname:   %db.other.db_name%
                user:     %db.other.user%
                password: %db.other.password%
        # if using pdo_sqlite as your database driver, add the path in parameters.yml
        # e.g. database_path: "%kernel.root_dir%/data/data.db3"
        # path:     "%database_path%"

    orm:
        default_entity_manager: default
        entity_managers:
            default:
                connection: default
                mappings:
                    CEBundle: ~
            mssqlDB:
                connection: mssqlDB
                mappings:
                    CEBundle: ~

        auto_generate_proxy_classes: "%kernel.debug%"
        #auto_mapping: true


# Swiftmailer Configuration
swiftmailer:
    transport: "%mailer_transport%"
    host:      "%mailer_host%"
    username:  "%mailer_user%"
    password:  "%mailer_password%"
    spool:     { type: memory }

#sylius configuration
sylius_cart:
    resolver: ce.cart_item_resolver
    classes: ~
    provider: sylius.cart_provider.default
    storage:  sylius.storage.session

sylius_order:
    driver: doctrine/orm
    classes:
        order_item:
            model: CE\CEBundle\Entity\CartItem

sylius_sequence:
    driver: doctrine/orm

#mopa configuration for forms and bootstrap
mopa_bootstrap:
    form:
        checkbox_label: 'widget'

Of note, if I watch the Resources tab in the Chrome Developer Tools, I can see that SYLIUS_SESSION does get set when I add an item to the cart.

I've tried changing the storage to cookie instead of session and pouring over the documents, but I'm at a loss as to what to do to fix this. My guess is it's probably something small, I just don't know what it is.

Thank you for any help in advance.

Kogenta
  • 61
  • 4

1 Answers1

1

In your config.yml file you are using sylius.cart_provider.default which means that you need to get the current Sylius Cart Provider before adding an item to it.

So that means in your controller, you will need to retrieve the cart_provider service like so:

// gets the current cart
$cart = $this->get('sylius.cart_provider')->getCart();

After that, you can create an $item like you are doing in the call to the ItemResolver::resolve() method and the item can be added to the cart.

You may also need to add the dispatcher events for the cart ITEM_ADD_INITIALIZE, CART_CHANGE, etc to your code to actually have the items appear in the cart.

Have a look at the CartItemEvent class for that. If you need help with that let me know.

Adam Elsodaney
  • 7,722
  • 6
  • 39
  • 65
Tragaknight
  • 413
  • 4
  • 10
  • I think this is already happening. The routes call CartController or CartItemController. Each of which calls $cart = $this->getCurrentCart() before doing anything, which is defined in Controll.php as $this->getProvider()->getCart(); getProvider is defined as return $this->container->get('sylius.cart_provider'); – Kogenta Jan 29 '15 at 20:50
  • In that case are you also using the form for CartItemType so that its variables are submitted in the request to the path sylius_cart_item_add i.e CartItemController ? As during the processing in the ItemResolver if your submitted data does not have any data in the $form->submit($data) variable (which comes through the request object) in ItemResolver (the original class not your class), then the item will not be added to the cart. Also, you need to dispatch the appropriate events in CartItemEvent to have the cart see the items added. – Tragaknight Jan 30 '15 at 03:59
  • Sorry for the delay in response. I am using the default CartItemController. Creating a link to add an item like the example here [link](http://sylius.readthedocs.org/en/latest/bundles/SyliusCartBundle/actions.html) So I simply pass the ID of the item I want to add to the action. The code for the add action can be found here [link](https://github.com/Sylius/SyliusCartBundle/blob/master/Controller/CartItemController.php) which redirects to the summary page after adding the item to the cart and making the database entries for cart and cart item (which show up in the database). – Kogenta Feb 04 '15 at 04:19
  • I'm not sure what I should change in this setup, since it's mostly using the default controllers and classes. I just extended ItemResolver and BaseCartItem to add the details for my own product information, as explained in [CartBundle Instructions](http://sylius.readthedocs.org/en/latest/bundles/SyliusCartBundle/installation.html) Sorry if I'm missing something simple here. – Kogenta Feb 04 '15 at 04:27
  • I also tried using a form submission like the example here for twig templates as shown [here](http://sylius.readthedocs.org/en/latest/bundles/SyliusCartBundle/templating.html) I got the same result in the [database](https://www.dropbox.com/s/3t6v6yxzerg22io/Sylius%20Cart%20and%20Item.png?dl=0) , but no cart information still on the summary page it redirects to. – Kogenta Feb 04 '15 at 05:15
  • Do you get any flash messages on the cart page once everything has run through and you see it added to the db but not on the cart summary page ? – Tragaknight Feb 05 '15 at 01:48
  • Nope. I checked the flashbag for errors and notices. Nothing. – Kogenta Feb 11 '15 at 21:10