For coders TYPO3 Tech Corner

[TYPO3] Turn Extbase cache for single views on or off?

[TYPO3] Turn Extbase cache for single views on or off?

How can you actually cache Extbase views or exclude them from the cache? And when is what useful at all? And how can we have caches flushed automatically? We try to bring this closer to you in this blog post.

Caches are great. These relieve the server and thus also the environment, provided they are used well. In addition, the ranking on Google & Co. also improves if the page can be loaded quickly. But caches are also annoying sometimes. Especially when developing a new feature or when there has been a change to a data set, but this change is not seen until days later.

Let's start from the beginning. Since the introduction of Extbase, individual views can easily be excluded from caching, while all views have been prepared for caching by default. As soon as a view can be cached, it can also be found in the search results of typo3/cms-indexed-search or stored statically with the help of the staticfilecache extension. But even without these advantages, the view is delivered much faster.

However, if there is an interaction with user input in the frontend - for example if a user profile is to be maintained, or if a filter is to reduce the results of a list view - caching becomes difficult or even impossible. With a simple filter, links with cHash values ​​could still be used, but with larger forms you quickly reach the limits of feasibility. In the worst case, you can even open up data protection problems if, for example, an application form is to be cached, but in the event of a validation error, the values ​​of the latest visitor suddenly become visible (note from the author: Everything has already been experienced).
In simplified terms, you can remember that detailed views in particular should be cached, all other views - especially those with visitor interaction - should be excluded from caching if you are unsure.

It can look like this in configurePlugin() - here listAction() and listAjaxAction() are excluded from caching:

\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin( 'users', 'Pi1', [ \In2code\Users\Controller\UserController::class => 'list, listAjax, detail' ], [ \In2code\Users\Controller\UserController::class => 'list, listAjax' ] );

ClearCacheCmd and Cache tags

However, if there is the possibility that the user can maintain his profile in the front end, the cache of his own detailed view should also expire immediately. And here you can wonderfully use cache tags. In the following example, tags are generated in the cache for all detailed views (tag: tx_users_detail). In addition, there are also individual tags such as tx_users_user_123 (where 123 is the UID of the data record):

public function initializeDetailAction() { $cacheTags = [ 'tx_users_detail', 'tx_users_user_' . (int)$this->request->getArgument('user') ]; $tsfeController = $GLOBALS['TSFE']; if ($tsfeController !== null) { $tsfeController->addCacheTags($cacheTags); } } public function detailAction(User $user = null): void { // Detail action stuff }

How you can delete the cache of the detail pages via Page TSConfig as soon as an editor makes a change in the backend (e.g. in a sysfolder) is already known to many (see official documentation on this):

TCEMAIN.clearCacheCmd = cacheTag:tx_users_detail

But now we want to delete the cache of a single page as soon as the user has changed his profile in the frontend in a corresponding Extbase form:

public function updateAction(User $user): void { $cacheManager = GeneralUtility::makeInstance(CacheManager::class); $cacheManager->flushCachesByTag('tx_users_user_' . $user->getUid()); // Update and redirect stuff }

Or the cache of all detail pages if, for example, we re-import all users from LDAP every night with the help of a Symfony command:

$cacheManager = GeneralUtility::makeInstance(CacheManager::class); $cacheManager->flushCachesByTag('tx_users_detail');

By the way: When using flushCachesByTag(), static cache files are also deleted if you are using the extension staticfilecache.

Use your own caches with the CacheManager

If you want to cache parts of your uncached view yourself, you can rely on the CacheManager in TYPO3. This requires a registration in the ext_localconf.php:

/** * Initialize cache manager configuration for EXT:users */ if (!is_array($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['users_filter'])) { $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['users_filter'] = []; }

If you want to inject the FrontendInterface in your class, you can define this in a Configuration/Services.yaml:

services: cache.users_filter: class: TYPO3\CMS\Core\Cache\Frontend\FrontendInterface factory: ['@TYPO3\CMS\Core\Cache\CacheManager', 'getCache'] arguments: ['users_filter']

If you were to make an "expensive" database query via the repository, you can also use a CacheService instead:

<?php declare(strict_types=1); namespace In2code\Users\Domain\Service; use In2code\Users\Utility\FrontendUtility; use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface; /** * Class GetFilterObjectsService */ class GetFilterObjectsService { /** * @var FrontendInterface|null */ private ?FrontendInterface $cache = null; /** * @var array */ protected array $objects = []; /** * Cache lifetime in seconds * * @var int */ protected int $lifetime = 86400; /** * GetFilterObjectsService constructor. * @param FrontendInterface $cache */ public function __construct(FrontendInterface $cache) { $this->cache = $cache; } /** * @return array */ public function get(): array { $objectsFromCache = $this->getObjectsFromCache(); if ($objectsFromCache === []) { // Call your Repository stuff here to git your objects $objects = $this->objectRepository->findBySomething(); $this->cacheObjects($objects); return $objects; } returN $objectsFromCache; } /** * @param array $objects * @return void */ protected function cacheObjects(array $objects): void { $this->cache->set( md5(FrontendUtility::getCurrentPageIdentifier() . 'users_filter_object'), $objects, ['users_filter_object'], $this->lifetime ); } /** * @return array */ protected function getObjectsFromCache(): array { return (array)$this->cache->get( md5(FrontendUtility::getCurrentPageIdentifier() . 'users_filter_object') ); } }

And: You can find the official documentation for this on the docs.typo3.org website.

Finally, I can only recommend the staticfilecache extension. This can speed up your TYPO3 by a factor of 230. Don't you think so? Just try it. As the icing on the cake, the extension also shows you in its own backend module which pages cannot be cached. This will help you track down major errors more quickly.

"Code faster, look at the time" - does this sound familiar to you?

How about time and respect for code quality? Working in a team? Automated tests?

Join us

Lesson cancellation - and now? New portal for the Bavarian school system.

For the Bavarian school system, we developed a new web app based on an existing but very outdated portal. The portal reports lesson cancellations throughout Bavaria and registered users are informed...

Go to news

SQL: Show all tables sorted by size in descending order

Lately I've been using the SQL command more often to find out which tables in the TYPO3 database are the largest. I've published the snippet once.

Go to news

TYPO3 12 with CKEditor 5: Styles in a single selection

If you set a link in the RTE in TYPO3, you may have to choose between different link classes, for example to create buttons in the frontend. What's new in TYPO3 12 is that you can select not just one...

Go to news

Null-Safe Operator in the TYPO3 area

With the introduction of PHP8, problems with undefined arrays or variables in general can arise in many places. Here are a few examples and simple solutions.

Go to news

Delete the first/last lines of a (SQL) file

There isn't much to say about the following commands. Sometimes it can be useful to delete the first (or last) X lines from a file. And if the file is too large to open with a conventional program, a...

Go to news

b13/container: Add and modify child elements in edit view

Unlike gridelements, you cannot manage the child elements in the B13 Container extension when you open the container in the editing view. I would be happy to show you how you can quickly install this...

Go to news