The checkout session is an object, which stores a set of data associated with checkout, like quote, customer, shipping, billing addresses, and else. Instead of relying on PHP’s $_SESSION object, which in turn, relies on phpsessid cookie, we pass the needed information, in our example, quoteId into the resolver’s arguments which allows us to set checkoutSession manually before configProvider get’s to read from it.

Where can be checkout session used?

Let’s have a look at the typical config provider from some arbitrary magento extension:

namespace ExampleVendor\\ExampleExtension;

class ExtensionConfigProvider implements ConfigProviderInterface {
  ...
	public function getConfig() {
    return [
      'payment' => [
        self::DIRECT_CODE => 
          'code' => self::DIRECT_CODE,
          'icons' => $this->getIcons(),
        ],
      ],
    ];
  }
	...
	private function getIcons() {
		$quoteId = '';

		if ($this->checkoutSession->getQuote()) {
			$quoteId = $this->checkoutSession->getQuote()->get('id')['entity_id'];
		}
	  ...
	}
	...
}

This config provider returns certain information in getConfig method, like icons using getIcons method. Note, that getIcons method actually uses checkoutSession to access quoteId which it might use for certain conditions in the logic.

Typically you would write a resolver for exposing config data to the ScandiPWA front end by dependency-injecting the configProvider model into the resolver’s constructor and returning needed values from it.

<aside> 💡 How to create a Resolver?

</aside>

Example resolver file which returns config values from original configProvider:

namespace Scandiweb\\MyExtension\\Model\\Resolver;

use ExampleExtension\\Model\\ExtensionConfigProvider;

class MyConfigResolver implements ResolverInterface {

	protected ExtensionConfigProvider extensionConfigProvider;
	
	public function __construct(
		// vvv Dependency injection of extension's config provider object
		ExtensionConfigProvider extensionConfigProvider
	) {
		$this->extensionConfigProvider = $extensionConfigProvider;
	}
	
	public function resolve([...]) {
					// vvv Getting the config object's result
	        $result = $this->extensionConfigProvider->getConfig();
	
	        if (!isset($result['payment'])) {
	            return [];
	        }
	
	        return [
	            'code' => $resultConfig['code'],
	            'icons' => $resultConfig['icons']
	        ];
	    }
}

But, let’s now try querying the resolver to see the result:

"errors": [
		{
			"debugMessage": "Warning: Undefined array key \\"entity_id\\" in ExtensionConfigProvider.php on line 91",
			"message": "Internal server error",
			"extensions": {
				"category": "internal"
			},
...

And, looks like entity_id is an undefined key which causes program to throw error. Let’s see where entity_id is used in ExtensionConfigProvider.php:

...	
private function getIcons() {
	$quoteId = '';

	if ($this->checkoutSession->getQuote()) {
	-> $quoteId = $this->checkoutSession->getQuote()->get('id')['entity_id'];
	}
  ...
}
...

As we see, entity_id should be accessed from the quote object which we should get from checkoutSession, but for some reason, checkoutSession->getQuote didn’t return us a valid value when called it inside the resolver, even though it returned a correct value in luma theme.

What is the Checkout Session and how does it work?

The checkout session is a service that manages customer session data during the checkout process. It is responsible for storing and retrieving information such as customer, quote, customer shipping and billing addresses, selected shipping and payment methods, and items in the customer's shopping cart.

Specifically, it’s a model located in the following namespace: Magento\\Checkout\\Model\\Session.

Further on, we can find that the checkout session model actually extends certain Magento\\Framework\\Session\\SessionManager class which is some sort of abstraction for working with session.

Untitled

And SessionManager itself is using php’s global $_SESSION to control the session data:

Untitled

In php, $_SESSION get’s associated using phpsessid cookie stored in user’s browser.

<aside> 💡 Read more about $_SESSION global in php

</aside>

Sometimes though, due to varnish cache or other reasons, the cookie is not correct which returns checkoutSession with outdated data on server side.

What’s the fix?

Checkout session data wouldn’t be empty if it was set manually in the resolver before executing config provider methods. In our case, we need to set quote data into the checkoutSession.

By setting the quote Id manually in the checkout session, we can ensure that the correct quote is being used in the config provider, because Magento\\Checkout\\Model\\Session’s getQuote method will attempt to resolve cart using it’s id:

Untitled

Modified resolver to set cart id before accessing config provider:

public function resolve(
        Field $field,
        $context,
        ResolveInfo $info,
        array $value = null,
        array $args = null
    ) {
				// ↓↓ Get cartId from the query's arguments
				$maskedCartId = $args['cartId'];
				
				$currentUserId = $context->getUserId();
				$storeId = (int)$context->getExtensionAttributes()->getStore()->getId();
				$cart = $this->getCartForUser->execute($maskedCartId, $currentUserId, $storeId);
				
				// ↓↓ Update checkout session with the cartId before calling getConfig()
				$this->checkoutSession->setQuoteId($cart->getId());

				$result = $this->configProvider->getConfig();

        if (!isset($result['payment'])) {
            return [];
        }

        return [
            'code' => $resultConfig['code'],
            'icons' => $resultConfig['icons']
        ];
		}

That’s it! Now we should get correct values from configProvider.