For coders TYPO3 Tech Corner

Use different domains within the same site in TYPO3

Use different domains within the same site in TYPO3

The site configuration in TYPO3 has been mandatory since TYPO3 10. This concept is well chosen and replaces the old sys_domain data records in the backend. But what if a certain area in the page tree should be accessible with several domains? If you have the same problem, we may have the solution for you.

I have often read the answer on various sources that you don't need several domains for one area in TYPO3. Finally, you can use an environment variable to assign different domains, for example if you want to develop locally or have a test environment.

Environment Variables

This is relatively easy to do by picking up this variable in the SiteConfiguration:

base: 'https://%env(HOST_MAIN)%/' rootPageId: 1 websiteTitle: 'My website' imports: - resource: 'EXT:sitepackage/Configuration/Routes/DefaultSiteConfiguration.yaml'

In the Apache configuration, this variable can then be easily set with:

SetEnv HOST_MAIN development.domain.org

Alternatively, this can also be easily defined in an .env file (here we recommend using helhum/dotenv-connector):

HOST_MAIN=development.domain.org
BaseVariants with own Condition

But there can also be cases in which you have to allow multiple domains for the same page tree section within the same TYPO3 instance (e.g. Production). This applies, for example, to areas in the intranet. In another case, however, an insurance customer would like us to access one area via two different domains. Depending on the domain, the content is then slightly different (we do not show the implementation here in order not to complicate the example).

This can be made possible with the help of BaseVariants in the SiteConfiguration. The only challenge: A condition that switches based on the current domain does not yet exist in TYPO3. We have to help a little here.

Let us assume that we have now defined two different domains in the .env file:

HOST_MAIN=domain1.org HOST_ALTERNATIVE=domain2.org

Then the SiteConfiguration could look like this:

base: 'https://%env(HOST_MAIN)%/' baseVariants: - base: 'https://%env(HOST_ALTERNATIVE)%/' condition: 'isAlternativeDomain("%env(HOST_ALTERNATIVE)%")' rootPageId: 1 websiteTitle: 'My website' imports: - resource: 'EXT:sitepackage/Configuration/Routes/DefaultSiteConfiguration.yaml'

The problem, however, is that the isAlternativeDomain() condition does not yet exist, and we have to make up for that in our sitepackage, for example. EXT:sitepackage/Configuration/ExpressionLanguage.php:

<?php return [ 'site' => [ \Vendor\Sitepackage\Condition\SiteConditionProvider::class ] ];

The related provider EXT:sitepackage/Classes/Condition/SiteConditionProvider.php:

<?php declare(strict_types = 1); namespace Vendor\Sitepackage\Condition; use Vendor\Sitepackage\Condition\FunctionsProvider\SiteConditionFunctionsProvider; use TYPO3\CMS\Core\ExpressionLanguage\AbstractProvider; /** * SiteConditionProvider */ class SiteConditionProvider extends AbstractProvider { /** * Constructor */ public function __construct() { $this->expressionLanguageProviders = [ SiteConditionFunctionsProvider::class, ]; } }

Last but not least the FunctionsProvider in EXT:sitepackage/Classes/Condition/FunctionsProvider/SiteConditionFunctionsProvider.php:

<?php declare(strict_types=1); namespace Vendor\Sitepackage\Condition\FunctionsProvider; use Symfony\Component\ExpressionLanguage\ExpressionFunction; use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; /** * SiteConditionFunctionsProvider */ class SiteConditionFunctionsProvider implements ExpressionFunctionProviderInterface { /** * @return array|ExpressionFunction[] */ public function getFunctions() { return [ $this->isAlternativeDomain(), ]; } /** * Site configuration: Can be used to decide if a baseVariant should be loaded * * Example: * baseVariants: * - base: 'https://%env(HOST_MAKLERNETZ)%/' * condition: 'isAlternativeDomain("%env(HOST_MAKLERNETZ)%")' * * @return ExpressionFunction */ protected function isAlternativeDomain(): ExpressionFunction { return new ExpressionFunction('isAlternativeDomain', function () { // Not implemented, we only use the evaluator }, function (array $existingVariables, string $alternativeDomain) { return GeneralUtility::getIndpEnv('HTTP_HOST') == $alternativeDomain; }); } }

In principle, that's all. The same area in the page tree can now be accessed via the domains domain1.org and domain2.org.

"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