You too can become a hero and support this Blog at GitHub Sponsors or Patreon.

More about support

Why do I need an Application Context?

Because you are a developer who is better save than sorry. You don't want to mess with the productive site because you "thought it was your local development system". You want to configure your system in a way that it behaves like you want in development as well as in production. What you don't want, is to change the settings on your local machine each time you synced with the productive database. You don't want to be in a position where you could forget to remove your private email address in that crucial application that you put there to test the email output before the next deployment.

Btw: if you don't set a proper application context, TYPO3 will always assume that you are in Production context. And you don't want to be the person, that runs his/her local development systems in Production context, am I right?

Still not convinced? OK, one last thing: It's fancy!

Finally got you? Good!

Top

How do I tell TYPO3 what Context it runs in?

A valid context must have one of the three root contexts: Production, Testing or Development. Any sub-contexts may be appended with a /. E.g. Production/Staging/Server2 would be a valid context. TYPO3 expects the context to be set in a dedicated environment variable called TYPO3_CONTEXT. This will not be there by default on your webserver. So you have to take care by yourself. For apache set the context in the vHost configuration for your site with the SetEnv Directive:

SetEnv TYPO3_CONTEXT Development

This can also be done in a .htaccess file. Alternatively mod_rewrite could be used to set the environment variable depending on rewrite conditions.

# Set context with mod_rewrite
# Rules to set ApplicationContext based on hostname
RewriteCond %{HTTP_HOST} ^dev\.example\.com$
RewriteRule .? - [E=TYPO3_CONTEXT:Development]

RewriteCond %{HTTP_HOST} ^www\.example\.com$
RewriteRule .? - [E=TYPO3_CONTEXT:Production]

For nginx, you can pass the context as a fastcgi parameter:

location ~ \.php$ {
   include         fastcgi_params;
   fastcgi_index   index.php;
   fastcgi_param   TYPO3_CONTEXT  Development;
   fastcgi_param   SCRIPT_FILENAME  $document_root$fastcgi_script_name;
}

There is also the way of setting the application context with a .env file. Composer based installations could use Helmuts dotenv-connector (GitHub) to set the context this way.

You can verify what context TYPO3 is currently running on, by checking the application information panel in the TYPO3 backend.

For CLI based requests you want to make sure your context is set, too. To do so, go to your home directory and find your .profile or .bashrc file. Set the environment variable in either of these files by exporting it:

export TYPO3_CONTEXT=Development

You can verify that the environment was updated successfully by running

env | grep TYPO3_CONTEXT

Alternatively you could specify the context with every CLI command. That might be usefull if you run multiple systems in different contexts on the same server.

TYPO3_CONTEXT=Development ./typo3/cli_dispatch.phpsh

So now that we know all this, let's move on.

Top

How can I utilize the Application Context?

I'm glad you asked. First of all I want to point out that I feel most comfortable with only adapting configuration to the current context, not code. But that is only an opinion and there might very well be good reasons to use a context-switch in your applications domain logic.

PHP

However, we focus on configuring our system based on the application context right now. In TYPO3 you can access the current context through an API. The core API  will return an instance of \TYPO3\CMS\Core\Core\ApplicationContext that holds the current context. Since TYPO3 9LTS there is a new way to retrieve this object (read more on that in my post New API classes in TYPO3 9LTS):

// Since TYPO3 9LTS
\TYPO3\CMS\Core\Core\Environment::getContext()

// Prior to TYPO3 9LTS
\TYPO3\CMS\Core\Utility\GeneralUtility::getApplicationContext()

As you might already know the main configuration of a TYPO3 system happens at typo3conf/LocalConfiguration.php and typo3conf/AdditionalConfiguration.php. While you dont want to add any code to the former, the latter is exactly the place to do so. So let's add some code to our AdditionalConfiguration.php:

<?php
$currentApplicationContext = \TYPO3\CMS\Core\Core\Environment::getContext();
$GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] .= ' (' . (string)$currentApplicationContext . ')';

if (!$currentApplicationContext->isProduction()) {
  $contextConfigFile = PATH_site . 'Configuration/' . (string)$currentApplicationContext . '.php';
  if (file_exists($contextConfigFile)) {
    require($contextConfigFile);
  }
}

What does this do? First of all we grep the current context. Then we append it to the name of the site, so that it will always be clear if we are in the backend of a development system or if we just hit the browser tab with the productive backend. This will result in something like this in the top left corner of your backend:

Additionally we include a configuration file if it can be found. In our example we will require the file Development.php in a folder called Configuration. We now can put all the settings that we want on a development system into that file and it will only be loaded on systems with TYPO3_CONTEXT set to Development. We enable displaying of errors and enhanced logging as well as other stuff you want to turn off in production for security or performance reasons.

We can also configure the database connection for TYPO3 in that file so we connect to our local database when developing.

So much for the global configuration of TYPO3. But what about TypoScript configuration? Those may be even more important!

Top

TypoScript

Relax. There is already a build-in TypoScript condition applicationContext to check for the current context:

[applicationContext == "Development"]
  plugin.tx_mysupercrucialpaymentapp {
    settings {
      debug = 1
      emailReceiver = me@work.com
      deactivateRealTransfer = 1
    }
  }
[end]

It is also possible to match all subcontexts by using a wildcard in a like() statement. Alternatively we can even use a regex with matches:

// Using a wildcard
[like(applicationContext, "Development*")]

// Using a regular expression
[applicationContext matches "/^Production/"]

Note that these TypoScript conditions will only work with TYPO3 9 or higher because they are using the symfony expression language (read my article to learn more about it). In older TYPO3 versions a conditon would look like this:
[applicationContext = Development*]

With this knowledge you have full control over all extensions and the behavior of the core on every server at any time. As a last advice I'd try to always put the production configuration as a default in my files and only overwrite in other contexts where it is needed.

Well, thats it. You should be fine now to make use of this little piece of best practise. Enjoy your context driven TYPO3 in the future!

Top

Further Information