Clearing your Website's Cloudflare Cache with Magento

When deplying code changes, sites using Magento 2 with Cloudflare as a reverse proxy often find the need to clear Magento’s cache and Cloudflare’s cache at the same time without having to clear the caches in two different places.

Luckily, with a Magento 2 module and adding in some Cloudflare API details, this can be achieved.

The below steps will demonstrate how this can be done, and both caches will be flushed by clicking on the Flush Cache Storage button in the Magento 2 admin under System -> Cache Management.

First of all, add the basic components required to register a module in the form of the registration.php and module.xml files.

// app/code/[Vendor]/[Module]/registration.php
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    '[Vendor]_[Module]',
    __DIR__
);
// app/code/[Vendor]/[Module]/etc/module.xml
<?xml version="1.0"?>
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="[Vendor]_[Module]" setup_version="1.0.0" />
</config>

Then run the module enable and database upgrade commands from the Magento 2 root directory.

$ /path/to/php bin/magento module:enable [Vendor]_[Module]
$ /path/to/php bin/magento setup:upgrade

Now, in order to purge Cloudflare's cache when flushing the cache storage in Magento, an observer is required for the adminhtml_cache_flush_all event.

With that said, define the Observer in an events.xml file.

// app/code/[Vendor]/[Module]/etc/adminhtml/events.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="adminhtml_cache_flush_all">
        <observer name="[module]_purge_cloudflare_cache" instance="[Vendor]\[Module]\Observer\PurgeCloudflareCache" />
    </event>
</config>

And proceed with adding the Observer file. I should note - although the API details are better off being added via Magento's Stores -> Configuration section, for the purpose of this example I have just added them to this file. Feel free to move around sections of code as you see fit.

// app/code/[Vendor]/[Module]/Observer/PurgeCloudflareCache.php
<?php
namespace [Vendor]\[Module]\Observer;

use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Encryption\EncryptorInterface;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Message\ManagerInterface;
use Psr\Log\LoggerInterface;

class PurgeCloudflareCache implements ObserverInterface
{
    /**
     * Cloudflare API URL
     */
    const CLOUDFLARE_API_URL = 'https://api.cloudflare.com/client/v4/zones/%s/purge_cache/';

    /**
     * @var ManagerInterface
     */
    public $messageManager;

    /**
     * @var LoggerInterface
     */
    public $logger;

    /**
     * PurgeCloudflareCache constructor.
     *
     * @param ManagerInterface $messageManager
     * @param LoggerInterface $logger
     */
    public function __construct(
        ManagerInterface $messageManager,
        LoggerInterface $logger
    ) {
        $this->messageManager = $messageManager;
        $this->logger         = $logger;
    }

    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $request = $this->getRequest();
        try {
            $response = $this->sendPurgeRequest($request);
            if ($response) {
                $decodedResponse = json_decode($response, true);
                if (isset($decodedResponse['success']) && $decodedResponse['success'] === true) {
                    $this->messageManager->addSuccessMessage(
                        'Cloudflare cache has been purged.
                        Please allow up to 30 seconds for changes to take effect.'
                    );
                } else {
                    $this->logger->error(
                        'Cloudflare error: ' .
                        $response
                    );
                    $this->messageManager->addErrorMessage(
                        'Cloudflare cache purge request failed. Please check Magento\'s log
                        files for more information.'
                    );
                }
            }
        } catch (\Exception $e) {
            $this->messageManager->addErrorMessage(
                'Magento encountered an unexpected problem. Please check Magento\'s log
                files for more information.'
            );
            $this->logger->critical($e->getMessage());
        }
    }

    private function getRequest()
    {
        $zoneId = 'YOUR SITE ZONE ID HERE';
        return sprintf(self::CLOUDFLARE_API_URL, $zoneId);
    }

    private function sendPurgeRequest($request)
    {
        $email = 'YOUR EMAIL ADDRESS ASSOCIATED TO YOUR CLOUDFLARE ACCOUNT';
        $apiKey = 'YOUR API KEY';
        $headers = [];
        if ($email !== '' && $apiKey !== '') {
            $headers = [
                "X-Auth-Email: {$email}",
                "X-Auth-Key: {$apiKey}",
                "Content-Type: application/json"
            ];
        }
        $curl_opt_array = [
            CURLOPT_URL => $request,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_CONNECTTIMEOUT => 10,
            CURLOPT_TIMEOUT => 10,
            CURLOPT_VERBOSE => 0,
            CURLOPT_SSL_VERIFYHOST => 0,
            CURLOPT_SSL_VERIFYPEER => 0,
            CURLOPT_HTTPHEADER => $headers,
            CURLOPT_POSTFIELDS => '{"purge_everything":true}',
            CURLOPT_CUSTOMREQUEST => 'DELETE'
        ];
        $ch = curl_init();
        curl_setopt_array($ch, $curl_opt_array);
        $response = curl_exec($ch);
        return $response;
    }
}

If you've followed the above steps correctly, you should see an additional Cloudflare-related message appear within the Magento admin after flushing the cache storage. The message will inform you whether a successful request has been sent to Cloudflare to purge the cache.

Introducing third party caching solutions to websites is becoming more popular, and if you're a freelance Magento 2 developer like myself, keeping on top of latest trends is important.

If you're not a developer and don't quite have the technical knowledge necessary to implement this solution, feel free to get in touch with me.