Code Monkey home page Code Monkey logo

cache-bags's Introduction

Extension icon

TYPO3 extension cache_bags

Coverage Maintainability CGL Release License
Version Downloads Supported TYPO3 versions Extension stability

πŸ“¦Β Packagist | πŸ₯Β TYPO3 extension repository | πŸ’ΎΒ Repository | πŸ›Β Issue tracker


An extension for TYPO3 CMS to build and register cache bags for enhanced cache control. Cache bags are built during runtime on uncached contents and can be used to define cache metadata like cache tags. In addition, they are used to calculate expiration dates for specific cache entries. This allows are fine-grained cache control, depending on the contents and their explicit dependencies like specific database contents or short-living API requests.

πŸš€ Features

  • Interface for cache bags with different cache scopes (e.g. pages)
  • Cache bag registry to handle generated cache bags
  • Cache expiration calculator for various use cases (query builder, query result etc.)
  • Event listener to override page cache expiration, based on registered page cache bags
  • Compatible with TYPO3 11.5 LTS, 12.4 LTS and 13.1

πŸ”₯ Installation

Composer

composer require cpsit/typo3-cache-bags

TER

Alternatively, you can download the extension via the TYPO3 extension repository (TER).

⚑ Usage

Cache bags

A cache bag can be seen as some type of metadata collection for a specific cache scope, e.g. for the current page (Frontend-related cache). It is used to control the cache behavior within a given scope, for example by defining custom cache tags or an explicit expiration date.

At the moment the following cache bags are supported:

Cache bag Scope
Cache\Bag\PageCacheBag Enum\CacheScope::Pages

Tip

You can also add your own cache bags by implementing Cache\Bag\CacheBag.

Here is an example about how to generate a new PageCacheBag for a given page:

use CPSIT\Typo3CacheBags;

$pageId = 72;
$expirationDate = new DateTimeImmutable('tomorrow midnight');

$cacheBag = Typo3CacheBags\Cache\Bag\PageCacheBag::forPage($pageId, $expirationDate);

Cache bag registry

In order to actually use a generated cache bag, each bag must be registered in the global Cache\Bag\CacheBagRegistry. This registry is defined as singleton instance and stores all registered cache bags during runtime.

The CacheBagRegistry should be injected using dependency injection or, if DI is not possible, by using GeneralUtility::makeInstance():

use CPSIT\Typo3CacheBags;
use TYPO3\CMS\Core;

$cacheBag = Typo3CacheBags\Cache\Bag\PageCacheBag::forPage(72);
$cacheBagRegistry = Core\Utility\GeneralUtility::makeInstance(Typo3CacheBags\Cache\Bag\CacheBagRegistry::class);
$cacheBagRegistry->add($cacheBag);

Dispatched events

When adding a new CacheBag to the registry, a CacheBagRegisteredEvent is dispatched. It is used, for example, to apply cache tags to the current Frontend request (using the shipped PageCacheBagRegisteredEventListener).

Get closest expiration date

Based on all registered cache bags, the registry is able to calculate the closest expiration date (if any cache bag provides an expiration date) for a given cache scope:

use CPSIT\Typo3CacheBags;
use TYPO3\CMS\Core;

$cacheBagRegistry = Core\Utility\GeneralUtility::makeInstance(Typo3CacheBags\Cache\Bag\CacheBagRegistry::class);
$expirationDate = $cacheBagRegistry->getExpirationDate(Typo3CacheBags\Enum\CacheScope::Pages);

This is used, for example, to apply the expiration date to the current Frontend page cache (using the shipped PageCacheLifetimeEventListener for TYPO3 β‰₯ v12 and PageCacheTimeoutHook for TYPO3 v11).

Cache expiration calculator

As already mentioned, cache bags may also store the expiration date of a targeted cache entry. The extension ships with a Cache\CacheExpirationCalculator that can be used to calculate an expiration date. The calculation is based on various input methods. At the moment, the following methods are available:

  • Calculation based on an Extbase query or query result
  • Calculation based on a Query Builder instance
  • Calculation based on an initialized Relation Handler
use CPSIT\Typo3CacheBags;
use TYPO3\CMS\Core;

// Use DI instead, calculator is *NOT* publicly available in the service container!
$cacheExpirationCalculator = Core\Utility\GeneralUtility::makeInstance(Typo3CacheBags\Cache\Expiration\CacheExpirationCalculator::class);
$connectionPool = Core\Utility\GeneralUtility::makeInstance(Core\Database\ConnectionPool::class);

$queryBuilder = $connectionPool->getQueryBuilderForTable('pages');
$queryBuilder->select('*')
    ->from('pages')
    ->where(
        $queryBuilder->expr()->or(
            $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter(72, Core\Database\Connection::PARAM_INT)),
            $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter(72, Core\Database\Connection::PARAM_INT)),
        ),
    )
;

$expirationDate = $cacheExpirationCalculator->forQueryBuilder('pages', $queryBuilder);
$cacheBag = Typo3CacheBags\Cache\Bag\PageCacheBag::forPage(72, $expirationDate);

Full example

Typical use cases of cache bags are list and detail views of custom records in Frontend scope. Here is a full example about how to use the PageCacheBag in list and detail views of a custom table:

use CPSIT\Typo3CacheBags;
use Psr\Http\Message;
use TYPO3\CMS\Core;
use TYPO3\CMS\Extbase;

final class BlogController extends Extbase\Mvc\Controller\ActionController
{
    public function __construct(
        private readonly BlogRepository $blogRepository,
        private readonly Typo3CacheBags\Cache\Bag\CacheBagRegistry $cacheBagRegistry,
        private readonly Typo3CacheBags\Cache\Expiration\CacheExpirationCalculator $cacheExpirationCalculator,
    ) {}

    public function listAction(): Message\ResponseInterface
    {
        /** @var Extbase\Persistence\QueryResultInterface<Blog> $blogArticles */
        $blogArticles = $this->blogRepository->findAll();

        // Create cache bag with reference to the queried table
        // and apply the calculated expiration date of all queried blog articles
        $cacheBag = Typo3CacheBags\Cache\Bag\PageCacheBag::forTable(
            Blog::TABLE_NAME,
            $this->cacheExpirationCalculator->forQueryResult(Blog::TABLE_NAME, $blogArticles),
        );

        // Add cache bag to registry
        $this->cacheBagRegistry->add($cacheBag);

        $this->view->assign('articles', $blogArticles);

        return $this->htmlResponse();
    }

    public function detailAction(Blog $article): Message\ResponseInterface
    {
        // Create cache bag with reference to the current article
        // and apply the article's endtime as cache expiration date
        $cacheBag = Typo3CacheBags\Cache\Bag\PageCacheBag::forRecord(
            Blog::TABLE_NAME,
            $article->getUid(),
            $article->getEndtime(),
        );

        // Add cache bag to registry
        $this->cacheBagRegistry->add($cacheBag);

        $this->view->assign('article', $article);

        return $this->htmlResponse();
    }
}

πŸ§‘β€πŸ’» Contributing

Please have a look at CONTRIBUTING.md.

πŸ’Ž Credits

The extension icon ("container") is a modified version of the original actions-container icon from TYPO3 core which is originally licensed under MIT License.

⭐ License

This project is licensed under GNU General Public License 2.0 (or later).

cache-bags's People

Contributors

renovate[bot] avatar eliashaeussler avatar

Stargazers

Martin Adler avatar Maik Schneider avatar

Watchers

Yana/Yannic Haupenthal avatar Dirk Wenzel avatar Thomas Kaiser avatar Ingo Dirscherl avatar Sebastian Kreideweiß avatar

cache-bags's Issues

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

composer
composer.json
  • php ~8.1.0 || ~8.2.0 || ~8.3.0
  • psr/event-dispatcher ^1.0
  • typo3/cms-core ~11.5.0 || ~12.4.0 || ~13.1.0
  • typo3/cms-extbase ~11.5.0 || ~12.4.0 || ~13.1.0
  • typo3/cms-frontend ~11.5.0 || ~12.4.0 || ~13.1.0
  • armin/editorconfig-cli ^1.8 || ^2.0
  • ergebnis/composer-normalize ^2.43
  • friendsofphp/php-cs-fixer ^3.57
  • phpstan/extension-installer ^1.4
  • phpstan/phpstan ^1.11
  • phpstan/phpstan-phpunit ^1.4
  • phpunit/phpcov ^9.0 || ^10.0
  • phpunit/phpunit ^10.1 || ^11.0
  • saschaegerer/phpstan-typo3 ^1.10
  • ssch/typo3-rector ^2.6
  • typo3/coding-standards ^0.7.0 || ^0.8.0
  • typo3/testing-framework ^7.0.2 || ^8.0.9
github-actions
.github/workflows/cgl.yaml
  • actions/checkout v4
  • shivammathur/setup-php v2
  • ramsey/composer-install v2
  • ramsey/composer-install v2
.github/workflows/release.yaml
  • actions/checkout v4
  • softprops/action-gh-release v2
  • actions/checkout v4
  • shivammathur/setup-php v2
.github/workflows/tests.yaml
  • actions/checkout v4
  • shivammathur/setup-php v2
  • ramsey/composer-install v2
  • actions/checkout v4
  • shivammathur/setup-php v2
  • ramsey/composer-install v2
  • actions/upload-artifact v4
  • actions/checkout v4
  • actions/download-artifact v4
  • paambaati/codeclimate-action v8.0.0
  • coverallsapp/github-action v2

  • Check this box to trigger a request for Renovate to run again on this repository

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.