Migration steps

Note

If you are not familiar with Composer, please read the following documents first:

It is recommended to perform a Composer migration using the latest TYPO3 major release to prevent facing bugs and issues that have been solved already in newer versions. In case you are using an older TYPO3 version in Legacy installation mode, you have two viable options:

  • Upgrade TYPO3 Legacy first, then do the migration to Composer. This is probably more straight-forward, as you can follow the Legacy Upgrade Guide, and then this guide.

  • Migrate old TYPO3 version to Composer first, then perform the major upgrade. This might cause some friction, because you have to utilize older versions of typo3/cms-composer-installers and dependencies like helhum/typo3-console or outdated extensions on Packagist. You will also need to inspect older versions of this guide that matches your old TYPO3 version, using the version selector of the documentation.

Delete files

Yes, that's true. You have to delete some files, because they will be created by Composer in some of the next steps.

You have to delete public/index.php, public/typo3/ and all the extensions inside public/typo3conf/ext/ that you have downloaded from the TYPO3 Extension Repository (TER) or any other resources like GitHub. You even have to delete your own extensions, if they are available in a separate Git repository and, for example, included as Git submodule.

Please keep only your sitepackage extension or any other extension, which was explicitly built for your current project and does not have an own Git repository.

Configure Composer

Create a file with name composer.json in your project root, not inside your web root.

You can use the composer.json from typo3/cms-base-distribution as an example. Use the file from the branch which matches your current version, for example 12.x.

However, this may require extensions you don't need or omit extensions you do need, so be sure to update the required extensions as described in the next sections.

You can also create the composer.json file via a composer init command. Or use the TYPO3 Composer Helper. Also advanced project builders like CPS-IT project-builder help you to initialize this most vital file of a Composer project with a guided approach.

Hint

If you see versions of the composer.json for versions older than TYPO3 v12, you may see references to a scripts section that would make use of helhum/typo3-console, and which also would need to be required as a package in your newly created composer.json. This is optional.

You can look at previous versions of the Base Distribution's composer.json, for differences between the TYPO3 versions.

Add all required packages to your project

You can add all your required packages with the Composer command composer require. The full syntax is:

typo3_root$
composer require anyvendorname/anypackagename:version

Example:

typo3_root$
composer require "typo3/minimal:^12"

This will utilize the Packagist repository by default, which is the de-facto standard for any Composer package.

Composer packages usually rely on a concept called SemVer <https://semver.org/ (semantic versioning). This splits any version number into three parts:

  • Major version (1.x.x)

  • Minor version (x.1.x)

  • Patch-level (x.x.1)

Only a major version should have intentional breaking changes (like new API, changed configuration directives, removed functionality).

New features can only be introduced via a new minor version (unless it is breaking).

Patch-level releases only fix bugs and security issues and should never add relevant features or even breaking changes.

By relying on this, the Composer version constraints of any installed package allow you to continuously update involved packages with an expected outcome (no breaking changes or non-working functionality).

There are different ways to define the version of the package you want to install. The most common syntaxes start with ^ (e.g. ^12.4) or with ~ (e.g. ~12.4.0). A full documentation can be found at https://getcomposer.org/doc/articles/versions.md

In short:

  • ^12.4 or ^12.4.0 tells Composer to add newest package of version 12.\* with at least 12.4.0. When a package releases version 12.9.5, you would receive that version. A version 13.0.1 would not be fetched. So this allows any new minor or patch-level version, but no new major version.

  • ~12.4.0 tells Composer to add the newest package of version 12.4.\* with at least 12.4.0, but not version 12.5.0 or 13.0.1. This would only fetch newer patch-level versions of a package.

You have to decide by yourself, which syntax fits best to your needs.

This applies to both the TYPO3 Core packages as well as extension packages, or even TYPO3-unrelated dependencies.

As a first step, you should only pick the TYPO3 Core extensions to ensure your setup works, and add third-party dependencies later.

Install the Core

Once the composer.json is updated accordingly, you can install additional system extensions:

typo3_root$
composer require typo3/minimal:^12.4
composer require typo3/cms-scheduler:^12.4
composer require ...

Or in one line:

typo3_root$
composer require typo3/minimal:^12.4 typo3/cms-scheduler:^12.4 ...

To find the correct package names, you can either take a look in the composer.json of the related system extension or follow the naming convention typo3/cms-<extension name with dash "-" instead of underscore "_">, e.g. typo3/cms-fluid-styled-content. You can also go to Packagist and search for typo3/cms- to see all listed packages.

Note

To find out all TYPO3 Core packages, you can visit the TYPO3 Composer Helper website. https://get.typo3.org/misc/composer/helper From this website, you can select TYPO3 Core Packages you need and generate the Composer command to require them.

Install extensions from Packagist

You already know the TYPO3 Extension Repository (TER) and always used it to install extensions? Fine. But with Composer, the required way is to install extensions directly from Packagist.

This is the usual way for most extensions used today. Alternatively, some extension authors or commercial providers offer a custom Composer repository that you can use (see below). The usage via composer require remains the same.

To install any TYPO3 extension, you need to know the package name. There are multiple ways to find it:

Notice on extension's TER page

Extension maintainers optionally can link their TYPO3 extension in TER with the according Composer package name on Packagist. Most maintainers already did that and if you search the extension in TER, you will see a message, which command and Composer package name you can use to install this extension.

../_images/TerComposerCommand.png

Note

The command composer req is short for composer require. Both commands exactly do the same and are interchangeable.

Search on Packagist

Packagist provides a flexible and quick search. Often you can search for the known TYPO3 extension key or name of the extension, and you will most likely find the package you are looking for.

Check manually

This is the most exhausting way. But it will work, even if the extension maintainer does not provide additional information.

  1. Search and open the extension, you want to install, in TER.

  2. Click button "Take a look into the code".

    ../_images/TerCodeLink.png
  3. Open file composer.json.

    ../_images/GithubComposerFile.png
  4. Search for line with property "name", it's value should be formatted like vendor/package.

    ../_images/GithubComposerName.png
  5. Check, if the package can be found on Packagist.

    ../_images/PackagistMask.png

Example: To install the mask extension in version 8.3.*, type:

typo3_root$
composer require mask/mask:~8.3.0

Install extension from version control system (e.g. GitHub, Gitlab, ...)

In some cases, you will have to install a TYPO3 extension, which is not available on Packagist or in the TER. Examples could be:

  • non-public extension only used by your company.

  • you forked and modified an existing extension.

  • commercial plugin / licensed download / Early Access (EAP)

As first step, you have to define the repository in your composer.json section repositories. In this example, you find the additional lines added to the composer.json from above:

/composer.json
 {
     "repositories": [
         {
             "type": "vcs",
             "url": "https://github.com/foo/bar.git"
         }
     ],
     "extra": {
         "typo3/cms": {
             "web-dir": "public"
         }
     }
 }

Ideally you should not manually edit a composer.json file, but instead utilize the Composer command to manipulate the file, like this:

typo3_root$
composer config repositories.foo-bar vcs https://github.com/foo/bar.git

The Git repository must point to a TYPO3 extension that provides a composer.json itself.

See composer.json for details on how these files should look like.

Git tags of the repository will be used as version numbers.

Apart from only adding a single Git repository, you can also add Composer repositories that aggregate multiple packages through tools like Satis, or also Private Packagist repositories.

If you fulfill these requirements, you can add your extension in the same way like the other examples:

typo3_root$
composer require foo/bar:~1.0.0

Include individual extensions like site packages

A project will often contain custom extensions, and at the least a sitepackage that provides the TYPO3-related project templates and configuration.

Before TYPO3 v12, these extensions were stored in a directory like typo3conf/ext/my_sitepackage. In Composer mode, you can easily add a custom repository within your project of the type path. This allows you to require your sitepackage as if it was a normal package. By doing this, you do not need to publish your sitepackage to a repository like GitHub, or publish a package on Packagist.

Usually these extensions are saved in a directory like <project_root>/packages/ or <project_root>/extensions/ (and no longer in typo3conf/ext/), so you would use:

typo3_root$
composer config repositories.local_packages path './packages/*'
composer require myvendor/sitepackage

This also means that your sitepackage needs to be contained in its own directory like <project_root>/packages/my_sitepackage/ and provide a composer.json file within that directory. That composer.json file would also list all the possible autoloading information of PHP classes that your sitepackage uses:

EXT:my_sitepackage/composer.json
{
     "autoload": {
         "psr-4": {
             "MyVendor\\Sitepackage\\": "Classes/"
         }
     }
}

Directory locations are always relative to where the extension-specific composer.json is stored.

Do not mix up the project-specific composer.json file with this package-specific composer.json file. Since autoloading information is specific to an extension, you usually do not list it in the project file.

To complete our example project's composer.json, it would look like this:

typo3_root/composer.json
{
    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/foo/bar.git"
        },
        {
            "type": "path",
            "url": "./packages/*"
        },
    ],
    "extra": {
        "typo3/cms": {
            "web-dir": "public"
        }
    }
}

After adding or changing paths in the autoload section you should run composer dumpautoload. This command will re-generate the autoload information and should be run anytime you add new paths to the autoload section in the composer.json.

After all custom extensions are moved away from typo3conf/ext/ you can remove the directory from your project. You may also want to adapt your .gitignore file to remove any entries related to that old directory.

New file locations

As final steps, you should move some files because the location will have changed for your site since moving to Composer.

The files listed below are internal files that should not be exposed to the webserver, so they are moved outside the public/ structure, in parallel to vendor/.

You should at least move the site configuration and the translations.

Move files:

typo3_root$
mv public/typo3conf/sites config/sites
mv public/typo3temp/var var
mv public/typo3conf/l10n var/labels

Important

The var directory may already exist. In that case, move the files individually. You can also delete the "old" files in public/typo3temp/var, unless you need to keep the log files or anything else that may still be relevant.

These locations have changed, note that TYPO3 v12+ moved some more configuration files to a new directory than TYPO3 v11:

Before

After

public/typo3conf/sites

config/sites

public/typo3temp/var

var

public/typo3conf/l10n

var/labels

public/typo3conf/LocalConfiguration.php

config/system/settings.php

public/typo3conf/AdditionalConfiguration.php

config/system/additional.php

public/typo3conf/system/settings.php

config/system/settings.php

public/typo3conf/system/additional.php

config/system/additional.php

public/typo3

vendor/typo3/

public/typo3conf/PackageStates.php

removed

public/typo3conf/ext

removed (replaced by vendor and e.g. packages)

N/A

public/_assets (new)

Have a look at Directory structure in "TYPO3 Explained". As developer, you should also be familiar with the Environment API.