skip to Main Content

The default context provider does not provide a cart object. There’s only channelContext, currencyContext, localeContext and customerContext.

Is it possible to get cart in twig template using Sylius template events?

For example like this:

sylius_ui:
    events:
        sylius.shop.layout.header.content:
            blocks:
                search:
                    enabled: true
                    template: "@App/Layout/Header/_search.html.twig"
                    priority: 10
                    context:
                        cart: how_to_pass_cart? # <-- How to pass cart

And using it in a template, for example:

{# @App/Layout/Header/_search.html.twig #}
{{ cart.itemsTotal }}

Right now, in the standard template, to display the cart, a render of the order controller is used with template substitution.

https://github.com/Sylius/Sylius/blob/a0ad0d1e4c61ed8ec30bbb39e36184cb910736b2/src/Sylius/Bundle/ShopBundle/Resources/views/Layout/Header/_cart.html.twig#L2

<div class="right aligned column">
    {{ render(url('sylius_shop_partial_cart_summary', {'template': '@SyliusShop/Cart/_widget.html.twig'})) }}
</div>

From my point of view this is not a very good solution.
Is there a way to get the cart via context parameter or ContextProvider in twig template?

2

Answers


  1. Chosen as BEST ANSWER

    Because we will not be able to inject services using the DefaultContextProvider, we can write our own ContextProvider.

    Create a file src/ContextProvider/CartContextProvider.php:

    <?php
    declare(strict_types=1);
    
    namespace AppContextProvider;
    
    use SyliusBundleUiBundleContextProviderContextProviderInterface;
    use SyliusBundleUiBundleRegistryTemplateBlock;
    use SyliusComponentOrderContextCartContextInterface;
    use SyliusComponentOrderModelOrderInterface;
    
    final class CartContextProvider implements ContextProviderInterface
    {
        public function __construct(
            private CartContextInterface $cartContext
        ){}
    
        public function provide(array $templateContext, TemplateBlock $templateBlock): array
        {
            $templateContext['cart'] = $this->getCart();
            return $templateContext;
        }
    
        public function supports(TemplateBlock $templateBlock): bool
        {
            return true;
        }
    
        private function getCart(): OrderInterface
        {
            return $this->cartContext->getCart();
        }
    }
    

    Register the new Context Provider as a service in the config/services.yaml:

    services:
        # ...
    
        AppContextProviderCartContextProvider:
            arguments:
                - '@sylius.context.cart'
            tags:
                - { name: sylius.ui.template_event.context_provider }
    

    After this, a cart will become available in any template. This can be checked in the twig template by calling the dump method. For example like this: {{ dump() }}


    Or you can use the Twig Extension solution from another answer in this thread.


  2. <?php
    
    declare(strict_types=1);
    
    namespace AppTwig;
    
    use SyliusComponentOrderModelOrderInterface;
    use SyliusComponentOrderContextCartContextInterface;
    use TwigExtensionAbstractExtension;
    use TwigTwigFunction;
    
    final class CartExtension extends AbstractExtension
    {
        private CartContextInterface $cartContext;
    
        public function __construct(CartContextInterface $cartContext)
        {
            $this->cartContext = $cartContext;
        }
    
        public function getFunctions(): array
        {
            return [
                new TwigFunction('get_cart', [$this, 'getCart']),
            ];
        }
    
        public function getCart(): OrderInterface
        {
            return $this->cartContext->getCart();
        }
    }
    
    

    Then in the Twig template you can do {% cart = get_cart() %}

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search