Configuration Files (ext_tables.php & ext_localconf.php)

Files ext_tables.php and ext_localconf.php are the two most important files for the execution of extensions within TYPO3. They contain configuration used by the system on almost every request. They should therefore be optimized for speed.

See Files and locations for a full list of file and directory names typically used in extensions.

Changed in version 10.0: These variables are no longer declared in ext_tables.php and ext_localconf.php files: $_EXTKEY, $_EXTCONF, T3_SERVICES, T3_VAR, TYPO3_CONF_VARS, TBE_MODULES, TBE_MODULES_EXT, TCA, PAGES_TYPES, TBE_STYLES

Changed in version 11.4: With 11.4 the files ext_localconf.php and ext_tables.php are scoped into the global namespace on being warmed up from the cache. Therefore use statements can now be used inside these files.

Warning

The content of the files ext_localconf.php and ext_tables.php must not be wrapped in a local namespace by extension author. This will result in nested namespaces and therefore cause PHP errors only solvable by clearing the caches via the Install Tool.

ext_localconf.php

– optional

ext_localconf.php is always included in global scope of the script, either frontend or backend.

Should Not Be Used For

While you can put functions and classes into ext_localconf.php, it is a really bad practice because such classes and functions would always be loaded. It is better to have them included only as needed.

Registering hooks or signals, XCLASSes or any simple array assignments to $GLOBALS['TYPO3_CONF_VARS'] options will not work for the following:

  • class loader
  • package manager
  • cache manager
  • configuration manager
  • log manager (= Logging Framework)
  • time zone
  • memory limit
  • locales
  • stream wrapper
  • error handler

This would not work because the extension files ext_localconf.php are included (loadTypo3LoadedExtAndExtLocalconf) after the creation of the mentioned objects in the Bootstrap class.

In most cases, these assignments should be placed in typo3conf/AdditionalConfiguration.php.

Example:

Register an exception handler in typo3conf/AdditionalConfiguration.php:

$GLOBALS['TYPO3_CONF_VARS']['SYS']['debugExceptionHandler'] = \Vendor\Ext\Error\PostExceptionsOnTwitter::class;

Should Be Used For

These are the typical functions that extension authors should place within ext_localconf.php

  • Registering hooks or signals, XCLASSes or any simple array assignments to $GLOBALS['TYPO3_CONF_VARS'] options
  • Registering additional Request Handlers within the Bootstrap
  • Adding any PageTSconfig
  • Adding default TypoScript via \TYPO3\CMS\Core\Utility\ExtensionManagementUtility APIs
  • Registering Scheduler Tasks
  • Adding reports to the reports module
  • Registering Icons to the IconRegistry
  • Registering Services via the Service API

deprecated

  • Registering Extbase Command Controllers (Extbase command controllers are deprecated since TYPO3 9. Use symfony commands as explained in Symfony Console Commands (cli))

Examples

Put a file called ext_localconf.php in the main directory of your Extension. It does not need to be registered anywhere but will be loaded automatically as soon as the extension is installed. The skeleton of the ext_localconf.php looks like this:

<?php
// all use statements must come first
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;

// Prevent Script from being called directly
defined('TYPO3') or die();

// encapsulate all locally defined variables
(function () {
    // Add your code here
})();

Adding default PageTSconfig

Default PageTSconfig can be added inside ext_localconf.php, see Setting default Page TSconfig:

//use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;

ExtensionManagementUtility::addPageTSConfig();

PageTSconfig available via static files can be added inside Configuration/TCA/Overrides/pages.php, see Register static Page TSconfig files:

ExtensionManagementUtility::registerPageTSConfigFile();

Adding default UserTSconfig

As for default PageTSconfig, UserTSconfig can be added inside ext_localconf.php, see: Setting default user TSconfig:

//use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;

ExtensionManagementUtility::addUserTSConfig();

ext_tables.php

– optional

ext_tables.php is not always included in the global scope of the frontend context.

This file is only included when

  • a TYPO3 Backend or CLI request is happening
  • or the TYPO3 Frontend is called and a valid backend user is authenticated

This file usually gets included later within the request and after TCA information is loaded, and a backend user is authenticated as well.

Hint

In many cases, the file ext_tables.php is no longer needed, since TCA definitions must be placed in Configuration/TCA/*.php files.

Should Not Be Used For

  • TCA configurations for new tables. They should go in Configuration/TCA/tablename.php
  • TCA overrides of existing tables. They should go in Configuration/TCA/Overrides/tablename.php
  • calling \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToInsertRecords() as this might break the frontend. They should go in Configuration/TCA/Overrides/tablename.php
  • calling \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile() as this might break the frontend. They should go in Configuration/TCA/Overrides/sys_template.php

For a descriptions of the changes for TCA (compared to older TYPO3 versions), please see the blogpost “Cleaning the hood: TCA” by Andreas Fernandez.

More information can be found in the blogpost Good practices in extensions (use TYPO3 blog).

Hint

ext_tables.php is cached.

Should Be Used For

These are the typical functions that should be placed inside ext_tables.php

  • Registering of backend modules or Adding a new Main Module :ref: ‘Example <extension-configuration-files-backend-module>’
  • Adding context-sensitive help to fields (via \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addLLrefForTCAdescr()) Example
  • Adding TCA descriptions (via \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addLLrefForTCAdescr())
  • Adding table options via \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::allowTableOnStandardPages() Example
  • Registering a scheduler tasks Scheduler Task Example
  • Assignments to the global configuration arrays $GLOBALS['TBE_STYLES'] and $GLOBALS['PAGES_TYPES']
  • Extending the Backend user settings

Examples

Put the following in a file called ext_tables.php in the main directory of your extension. The file does not need to be registered but will be loaded automatically:

<?php
// all use statements must come first
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;

defined('TYPO3') or die();

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

Registering a backend module

You can register a new backend module for your extension via ExtensionUtility::registerModule():

// use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;

ExtensionUtility::registerModule(
   'ExtensionName', // Extension Name in CamelCase
   'web', // the main module
   'mysubmodulekey', // Submodule key
   'bottom', // Position
   [
       'MyController' => 'list,show,new',
   ],
   [
       'access' => 'user,group',
       'icon'   => 'EXT:my_extension/ext_icon.svg',
       'labels' => 'LLL:EXT:my_extension/Resources/Private/Language/locallang_statistics.xlf',
   ]
);

For more information on backend modules see backend module API.

Adding context-sensitive help to fields

Add the following to your extensions ext_tables.php in order to add context-sensitive help for the corresponding field:

// use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;

ExtensionManagementUtility::addLLrefForTCAdescr(
    'tx_domain_model_foo',
    'EXT:myext/Resources/Private/Language/locallang_csh_tx_domain_model_foo.xlf'
);

For more information see context-sensitive help.

Allowing a tables records to be added to Standard pages

By default new records of tables may only be added to Sysfolders in TYPO3. If you need to allow new records of your table to be added on Standard pages call:

// use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;

ExtensionManagementUtility::allowTableOnStandardPages(
   'tx_myextension_domain_model_mymodel'
);

Registering a scheduler task

Scheduler tasks get registered in the ext_tables.php as well. Note that the Sysext “scheduler” has to be installed for this to work.

// use TYPO3\CMS\Scheduler\Task\CachingFrameworkGarbageCollectionTask;
// use TYPO3\CMS\Scheduler\Task\CachingFrameworkGarbageCollectionAdditionalFieldProvider;

// Add caching framework garbage collection task
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][CachingFrameworkGarbageCollectionTask::class] = array(
     'extension' => 'your_extension_key',
     'title' => 'LLL:EXT:your_extension_key/locallang.xlf:cachingFrameworkGarbageCollection.name',
     'description' => 'LLL:EXT:your_extension_key/locallang.xlf:cachingFrameworkGarbageCollection.description',
     'additionalFields' => \CachingFrameworkGarbageCollectionAdditionalFieldProvider::class
);

For more information see the documentation of the Sys-Extension scheduler.

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 files global scope - that would make the cached script concept break.

  • You MUST NOT rely on the PHP constant __FILE__ for detection of 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 e.g. \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.

    -namespace {
    -}
    
  • You CAN use use statements starting with TYPO3 11.4:

    // 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;
    
  • 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.

// You can use declare strict and other directives which must be placed at the top of the file
+declare(strict_types=1)
  • You MUST NOT check for values of the removed TYPO3_MODE or TYPO3_REQUESTTYPE constants (e.g. if (TYPO3_MODE === 'BE')) or the ApplicationType within these files as it limits the functionality to cache the whole systems’ configuration. Any extension author should remove the checks, and re-evaluate if these context-depending checks could go inside the hooks / caller function directly., e.g. do not do:
// do NOT do this:
-if (TYPO3_MODE === 'BE')
  • 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.
<?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();
  • You MUST use the extension name (e.g. “tt_address”) instead of $_EXTKEY within the two configuration files as this variable is no longer loaded automatically.
  • However, due to limitations to TER, the $_EXTKEY option MUST be kept within an extension’s ext_emconf.php.
  • 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:

<?php
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
defined('TYPO3') or die();

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

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.

Additional tips:

  • TYPO3\CMS\Core\Package\PackageManager::getActivePackages() contains information about whether the module is loaded as local or system type in the packagePath key, including the proper paths you might use, absolute and relative.