Alter Page Cache for using cookies in Drupal 9
To modify Page Caching behavior we need to understand the following Drupal Core concepts which are mentioned below.
- Internal page cache ( \Drupal\page_cache\StackMiddleware\PageCache): In Drupal, internal page caching refers to a built-in caching mechanism that caches the entire HTML output of rendered pages.
- Content negotiation (\Drupal\Core\StackMiddleware\NegotiationMiddleware): Content negotiation is used to deliver the response in the preferred format requested by the client, which could be HTML, JSON, XML, or other formats.
- Session handling (\Drupal\Core\StackMiddleware\Session): Session handling is used to store and maintain user-specific information across the site.
Let’s start with an example :
Problem: The view Page is getting cached when using Cookies as Contextual Filter.
Solution: Let’s add cookies based on location (Mumbai, Delhi, etc). If we want to alter page caching based on cookie value which is Mumbai, Delhi, etc., then we will start creating a custom view plugin for fetching cookies value and passing data in the views as an argument. For resolving, the view page is getting cached when using cookies as a contextual filter, we can alter Page Cache and set our dynamic cookies value with Page Cache Id. So, In this blog, we will see how we can achieve adding cookies value to the page cache using Drupal StackPHP middlewares and ServiceProvider.
Here we are extending the Internal page cache class and using its predefined methods as per our requirement. Before extending the Page Cache class, we need to create custom service provider by extending the Drupal Core Service Provide Base class and Service Provider Interface in our custom module.
Firstly, Drupal automatically discovers only one service provider per Drupal module. Implement a class extending ServiceProviderBase and the alter() method to modify existing services. The naming convention for the service provider PHP class is camel-cased Drupal module name plus ServiceProvider.php. You cannot name the service provider class, just ServiceProvider.php. It must be [MODULE-NAME-CAMEL-CASE]ServiceProvider.php. So we will create customCommonServiceProvider.php file in our custom module. This file was placed at /web/modules/custom/customCommon/src/customCommonServiceProvider.php
Let’s understand this with the below code.
<?php namespace Drupal\customCommon; use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\DependencyInjection\ServiceProviderBase; use Drupal\Core\DependencyInjection\ServiceProviderInterface; /** * Alter page cache service. */ class customCommonServiceProvider extends ServiceProviderBase implements ServiceProviderInterface { /** * {@inheritdoc} */ public function alter(ContainerBuilder $container) { if ($container->hasDefinition('http_middleware.page_cache')) { $definition = $container->getDefinition('http_middleware.page_cache'); $definition->setClass('Drupal\customCommon\StackMiddleware\AlterPageCache'); } }
In the above code, we extend ServiceProviderBase core class and ServiceProviderInterface. We call alter method with ContainerBuilder as an argument. In the container, we check the middleware page cache definition existence. Then we will get and set our AlterPageCache class in it.
Secondly, We will create a StackMiddleware folder in the src folder of our custom module. In this folder, we have to create an AlterPageCache.php file. So the final path of the file will be /web/modules/custom/customCommon/src/StackMiddleware/AlterPageCache.php
<?php namespace Drupal\customCommon\StackMiddleware; use Drupal\page_cache\StackMiddleware\PageCache; use Symfony\Component\HttpFoundation\Request; /** * Alter page cache service and extend Cookies. */ class AlterPageCache extends PageCache { /** * Get cookie id cached. */ protected function getCacheId(Request $request) { // Get cookie value and append into cid. $cookiesCache = $request->cookies->get('currentLocation', NULL); if (!isset($this->cid)) { $cidParts = [ $request->getSchemeAndHttpHost() . $request->getRequestUri(), $request->getRequestFormat(NULL), $cookiesCache, ]; $this->cid = implode(':', $cidParts); } return $this->cid; } }
In this file, we extend the internal page cache class and override its getCacheId method to set out cookies that we get from the request and return the cache id.
Conclusion: Following the above steps, one can alter the page caching based on a custom cookie value. Let us know in case of any queries; please feel free to reach out via comments and subscribe to our blogs.