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?

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.

Back

"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