Configuration Files (ext_tables.php & ext_localconf.php)

The files ext_tables.php and ext_localconf.php contain configuration used by the system and in requests. They should therefore be optimized for speed.

See File structure for a full list of file and directory names typically used in extensions.

Changed in version 11.4

With TYPO3 v11.4 the files ext_localconf.php and ext_tables.php are scoped into the global namespace on warmup of the cache. Therefore, use statements can now be used inside these files.

Rules and best practices

The following apply for both ext_tables.php and ext_localconf.php.

As a rule of thumb: Your ext_tables.php and ext_localconf.php files must be designed in a way that they can safely be read and subsequently imploded into one single file with all configuration of other extensions.

  • You must not use a return statement in the file's global scope - that would make the cached script concept break.
  • You must not rely on the PHP constant __FILE__ for detection of the include path of the script - the configuration might be executed from a cached file with a different location and therefore such information should be derived from, for example, \TYPO3\CMS\Core\Utility\GeneralUtility::getFileAbsFileName() or \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath().
  • You must not wrap the file in a local namespace. This will result in nested namespaces.

    Diff of EXT:my_extension/ext_localconf.php | EXT:my_extension/ext_tables.php
    -namespace {
    -}
    Copied!
  • You can use use statements starting with TYPO3 v11.4:

    Diff of EXT:my_extension/ext_localconf.php | EXT:my_extension/ext_tables.php
    // you can use use:
    +use TYPO3\CMS\Core\Resource\Security\FileMetadataPermissionsAspect;
    +
    +$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'][] =
    +   FileMetadataPermissionsAspect::class;
    // Instead of the full class name:
    -$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'][] =
    -   \TYPO3\CMS\Core\Resource\Security\FileMetadataPermissionsAspect::class;
    Copied!
  • You can use declare(strict_types=1) and similar directives which must be placed at the very top of files. They will be stripped and added once in the concatenated cache file.

    Diff of EXT:my_extension/ext_localconf.php | EXT:my_extension/ext_tables.php
    // You can use declare strict and other directives
    // which must be placed at the top of the file
    +declare(strict_types=1);
    Copied!
  • You must not check for values of the removed TYPO3_MODE or TYPO3_REQUESTTYPE constants (for example, if (TYPO3_MODE === 'BE')) or use the \TYPO3\CMS\Core\Http\ApplicationType class within these files as it limits the functionality to cache the whole configuration of the system. Any extension author should remove the checks, and re-evaluate if these context-depending checks could go inside the hooks / caller function directly, for example, do not:

    Diff of EXT:my_extension/ext_localconf.php | EXT:my_extension/ext_tables.php
    // do NOT do this:
    -if (TYPO3_MODE === 'BE')
    Copied!
  • You should check for the existence of the constant defined('TYPO3') or die(); at the top of ext_tables.php and ext_localconf.php files right after the use statements to make sure the file is executed only indirectly within TYPO3 context. This is a security measure since this code in global scope should not be executed through the web server directly as entry point.

    EXT:my_extension/ext_localconf.php | EXT:my_extension/ext_tables.php
    <?php
    use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
    
    // put this at top of every ext_tables.php and ext_localconf.php right after
    // the use statements
    defined('TYPO3') or die();
    Copied!
  • You must use the extension name (for example, "tt_address") instead of $_EXTKEY within the two configuration files as this variable is no longer loaded automatically.
  • However, due to limitations in the TYPO3 Extension Repository, the $_EXTKEY option must be kept within an extension's ext_emconf.php file.
  • You should use a directly called closure function to encapsulate all locally defined variables and thus keep them out of the surrounding scope. This avoids unexpected side-effects with files of other extensions.

The following example contains the complete code:

EXT:my_extension/ext_localconf.php | EXT:my_extension/ext_tables.php
<?php
declare(strict_types=1);

use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;

defined('TYPO3') or die();

(function () {
    // Add your code here
})();
Copied!

Additionally, it is possible to extend TYPO3 in a lot of different ways (adding TCA, backend routes, Symfony console commands, etc), which do not need to touch these files.