* PHP 5.6 is now the minimum required version and up to PHP 7.3 is supported. We strongly recommend you only use [supported versions of PHP](https://www.php.net/supported-versions.php).
### Using recipes instead of requiring individual modules
The SilverStripe CMS and SilverStripe Framework are becoming more modular. Many of the secondary features contained in SilverStripe CMS 3 and SilverStripe Framework 3 have been moved to separate modules.
SilverStripe 4 introduces the concept of _recipes_. Recipes are a combination of modules to achieve a common pattern.
Read the [Switching to recipes](#switching-to-recipes) section of this guide for more information about how recipes work.
### Automating your upgrades using the SilverStripe Upgrader tool
We've developed [an upgrader tool](https://github.com/silverstripe/silverstripe-upgrader) which you can use to help
with the upgrade process. The upgrader is unlikely to completely upgrade your project, however it can take care of the most tedious part of the upgrade.
[Composer](http://getcomposer.org) is a tool for managing PHP dependencies. SilverStripe 4 requires composer version _1.1_ or greater. Read the [SilverStripe _Getting started_ guide](/getting_started/composer) for more details.
Using the upgrader is not mandatory, but it can speed up the process. Although SilverStripe 4 can run in both PHP 5.6 and PHP 7, the upgrader itself requires PHP 7.1.
1. [Download the upgrader as a PHAR executable](https://silverstripe.github.io/silverstripe-upgrader/upgrade-code.phar) or `wget https://silverstripe.github.io/silverstripe-upgrader/upgrade-code.phar`
2. Make the file executable `chmod +x upgrade-code.phar`
3. Move the file to a folder in your path, for example `sudo mv upgrade-code.phar /usr/local/bin/upgrade-code`
When starting a new upgrade project, it's a good idea to check if you are using the latest release of the upgrader. Releases from 1.4 and above ship with a `self-update` command and will warn you if you are using an outdated version. If you are upgrading from a prior version, follow the regular installation instructions and override your existing executable.
You can run `upgrade-code help` to get more information about the upgrader or `upgrade-code help command-name` to information about a specific command.
*`--root-dir` which can be use to explicitly specify the root of your project. If this is not specified then the current working directory is assumed to be the root of the project.
Sample upgrader commands in this guide assume your working directory is the root of your SilverStripe project. You'll need to use the `--root-dir` flag if that's not the case.
You can install the upgrader globally with composer. This can make it easier to update to newer releases, however you can get dependency conflicts if you have other packages installed globally.
Add your global composer bin directory to your path. On \*nix system, this directory is normally located at `$HOME/.composer/vendor/bin`. On Windows system, this directory is normally located at `C:\Users\<COMPUTER NAME>\AppData\Roaming\Composer\vendor\bin`. You can find the exact location by running this command:
The upgrader comes with an `all` command. This command will attempt to run all the upgrader commands in the same order as this guide. This is unlikely to work on your first try, but can be a good way to get started without going through this entire guide.
Creating a dedicated branch in your source version control system to track your upgrade work can help you manage your upgrade. If you're upgrading a big project, you should consider creating individual branches or commits for each step.
You can add a `--recipe-core-constraint` flag to target a specific version of `silverstripe/recipe-core`. By default, the project will be upgraded to the latest stable version. If you are upgrading a CWP project, you can use `--cwp-constraint` instead to target a specific version of `cwp/cwp-core`.
The upgrader uses [caret version constraint](https://getcomposer.org/doc/articles/versions.md#caret-version-range-) by default. This will cause composer to install compatible minor releases. You can use the `--strict` option if you want to use the more conservative [tilde version constraints](https://getcomposer.org/doc/articles/versions.md#tilde-version-range-).
If the `recompose` command can't find a compatible version for one of your modules, it will keep this dependency in your `composer.json` file with its existing constraint.
If your SilverStripe 3 project requires the `silverstripe/cms` module, replace that dependency with `silverstripe/recipe-cms`. The version constraint for `silverstripe/recipe-cms` must match your targeted version of SilverStripe:
If your SilverStripe 3 project requires the `silverstripe/framework` module without `silverstripe/cms`, replace `silverstripe/framework` with `silverstripe/recipe-core`. The version constraint for `silverstripe/recipe-core` must match your targeted version of SilverStripe:
The following modules are implicitly required by `silverstripe/recipe-core`. They can be removed from your `composer.json` dependencies if you are using `silverstripe/recipe-core` or `silverstripe/recipe-cms`.
The following modules are implicitly required by `silverstripe/recipe-cms`. They can be removed from your `composer.json` dependencies if you are using `silverstripe/recipe-cms`.
*`silverstripe/admin`
*`silverstripe/asset-admin`
*`silverstripe/campaign-admin`
*`silverstripe/cms`
*`silverstripe/errorpage`
*`silverstripe/reports`
*`silverstripe/graphql`
*`silverstripe/siteconfig`
*`silverstripe/versioned`
*`silverstripe/recipe-core`
Take for example the following SilverStripe 3 `composer.json`.
```json
{
"name": "app/cms-website",
"require": {
"silverstripe/cms": "3.6.5@stable",
"silverstripe/framework": "3.6.5@stable",
"silverstripe/reports": "3.6.5@stable",
"silverstripe/siteconfig": "3.6.5@stable"
}
}
```
After switching to SilverStripe 4 recipes, the `composer.json` file should look like this.
If you would rather explicitly define your dependencies, you can do so. Update the `silverstripe/framework` constraint and `silverstripe/cms` constraint to match your targeted minor version of SilverStripe 4. If you use `silverstripe/reports` and `silverstripe/siteconfig`, update their constraints as well.
In most cases, you'll also want to require the same modules as the equivalent recipes. If you don't, your users will likely lose some features after the upgrade is completed.
Take for example the following SilverStripe 3 `composer.json`.
```json
{
"name": "app/cms-website",
"require": {
"silverstripe/cms": "3.6.5@stable",
"silverstripe/framework": "3.6.5@stable",
"silverstripe/reports": "3.6.5@stable",
"silverstripe/siteconfig": "3.6.5@stable"
}
}
```
After switching to SilverStripe 4 and explicitly defining your dependencies, the `composer.json` file should look like this.
```json
{
"name": "app/cms-website",
"require": {
"silverstripe/cms": "~4.1.0",
"silverstripe/framework": "~4.1.0",
"silverstripe/reports": "~4.1.0",
"silverstripe/siteconfig": "~4.1.0",
"silverstripe/admin": "~1.1.0",
"silverstripe/asset-admin": "~1.1.0",
"silverstripe/campaign-admin": "~1.1.0",
"silverstripe/errorpage": "~1.1.0",
"silverstripe/graphql": "~1.1.0",
"silverstripe/versioned": "~1.1.0"
}
}
```
#### Updating third party dependencies
If you project requires third party modules, you'll need to adjust their associated constraint. This will allow you to retrieve a SilverStripe 4 compatible version of the module.
[Look up the module on Packagist](https://packagist.org/) to see if a SilverStripe 4 version is provided.
Take for example the following SilverStripe 3 `composer.json`.
```json
{
"name": "app/cms-website",
"require": {
"silverstripe/framework": "3.6.5@stable",
"silverstripe/cms": "3.6.5@stable",
"dnadesign/silverstripe-elemental": "^1.8.0"
}
}
```
Looking at the [Packagist entry for `dnadesign/silverstripe-elemental`](https://packagist.org/packages/dnadesign/silverstripe-elemental#2.0.0), you can see that versions 2.0.0 and above of this module are compatible with SilverStripe 4. So you can update that constraint to `^2.0.0`.
Alternatively, you can set a very permissive constraint and let composer find a SilverStripe 4 compatible version. After you're done updating your dependencies, make sure you adjust your constraints to be more specific.
Once you've updated your third-party modules constraints, try updating your dependencies by running `composer update`. If composer can't resolve all your dependencies it will throw an error.
If the maintainer of the module is in the process of upgrading to SilverStripe 4, a development version of the module might be available. In some cases, it can be worthwhile to look up the repository of the module or to reach out to the maintainer.
Another possible cause of a dependency conflict is the use of private packages. The `recompose` command does not take into consideration the `repositories` entries in your project's `composer.json` file. Constraints on private packages have to be defined manually.
Read the [Composer Repositories](https://getcomposer.org/doc/05-repositories.md) documentation for more information on private repositories.
If you're going to install a development version of third party modules, you should consider adding the following entries to your `composer.json` file:
To upgrade an incompatible module yourself, you can try the options below.
##### Fork the affected module and upgrade it yourself
This approach has the advantage of keeping the module out of your codebase. It also makes it easy to reuse the code afterwards. This requires you to track the code in a separate repository.
When forking the module, you should convert it to a vendor module.
Upgrade the module so it works with version `4` of SilverStripe, commit and push your changes to your forked repository.
See [Upgrading a module](./upgrading_module) for more information on how to upgrade a SilverStripe module.
If you're taking the time to upgrade a third party module, consider doing a pull request against the original project so other developers can benefit from your work. Or you can release your fork as a separate module.
If you want to keep your fork private, you can include it in your project by adding a `vcs` repository entry in your composer file:
##### Integrate the affected module into your project's codebase
You can add the module codebase to your own project. This is the simplest option, but it increases the complexity of your project, and the amount of code you have to maintain, therefore it is discouraged.
If you choose this option, the module will be treated as a root module, which is discouraged in SilverStripe 4.
1. Remove the module from your dependencies by manually editing your `composer.json` file. Do not use `composer remove` as this will remove your folder.
2. Update your `.gitignore` file to track the module.
3. Remove the `composer.json` from the module.
Note that all commands that need to be applied to `mysite` will also need to be applied to any root modules you are tracking in your project.
#### Removing the module from your project
You can remove the module completely if you do not need it.
This can be done simply by removing the dependency: `composer remove <package>`
Once you've resolved all conflicts in your `composer.json` file, `composer update` will be able to run without errors.
This will install your new dependencies. You'll notice many of the folders in the root of your project will disappear. That's because SilverStripe 4 modules can be installed in the vendor folder like generic PHP packages.
If you've decided to use recipes, some generic files will be copied from the recipe into your project. The `extra` attribute in your `composer.json` file will be updated to keep track of those new files.
This is a good point to commit your changes to your source control system before moving on to the next step.
## Step 2 - Update your environment configuration {#env}{#step2}
`.env` file. It follows a syntax similar to a `.ini` file for key/value pair assignment. Your `.env` file may be placed in your project root, or one level above your project root.
Read the [Environment management](/getting_started/environment_management/) documentation to learn more about configuring your project's environment.
### Automatically convert `_ss_environment.php` to `.env`
If you have installed the upgrader tool, you can use the `environment` command to generate a valid `.env` file from your existing `_ss_environment.php` file.
If your `_ss_environment.php` file contains unusual logic (conditional statements or loops), you will get a warning. `upgrade-code` will still try to convert the file, but you should double-check the output. Omit the `--write` flag to do a dry-run.
### Manually convert `_ss_environment.php` to `.env`
Create a `.env` file in the root of your project. Replace `define` statements from `_ss_environment.php` with `KEY=VALUE` pairs in `.env`.
Most SilverStripe 3 environment variables have been carried over to SilverStripe 4. See [Environment Management docs](/getting_started/environment_management/) for the full list of available variables. Your `.env` file can contain environment variables specific to your project as well.
The global array `$_FILE_TO_URL_MAPPING` has been removed and replaced with the `SS_BASE_URL` environment variable. `SS_BASE_URL` expects an absolute url with an optional protocol. The following are values would be valid entries for `SS_BASE_URL`:
*`http://localhost/`
*`https://localhost/`
*`//localhost/`
For example, take the following `_ss_environment.php` file.
The global values `$database` and `$databaseConfig` have been deprecated. Your database configuration details should be stored in your `.env` file. If you want to keep your database configuration in `_config.php`, you can use the new `DB::setConfig()` api, however this is discouraged.
Requiring `conf/ConfigureFromEnv.php` is is no longer necessary. You should remove any references to it in `_config.php`.
The removal of the `_ss_environment.php` file means that conditional logic is no longer available in the environment
variable set-up process. This encouraged bad practice and should be avoided. If you still require conditional logic early in the bootstrap, this is best placed in the `_config.php` files.
To access environment variables, use the `SilverStripe\Core\Environment::getEnv()` method. To define environment variables, use the `SilverStripe\Core\Environment::setEnv()` method.
### Finalising your environment upgrade
It's inadvisable to track your `.env` file in your source control system as it might contain sensitive information.
You should ignore the `.env` file by adding an entry to your `.gitignore` file. You can create a sample environment configuration by duplicating your `.env` file as `.env.sample`, and removing sensitive information from it. You can safely delete your legacy `_ss_environment.php` if you want.
If you want your codebase to comply with the PSR-4 standard, make sure sub-directories of your code folder are using the _UpperCamelCase_ naming convention. For example, `mysite/code/page_types` should be renamed to `mysite/code/PageTypes`.
By default, the same namespace will be applied to all your classes regardless of which directory they are in. If you want to apply different namespaces to different folders to be compliant with PSR-4, combine the `--recursive` option with the `--psr4` option. Your folder structure must be PSR-4 compliant for this to work. If you want to do a dry-run, omit the `--write` option to see a preview of all changed project files.
Go through each PHP file under `mysite/code` and add a `namespace` statement at the top, *with the exception of the files for `Page` or `PageController`*.
For example, if `mysite/code/ProductService.php` is using the `ExplosiveTennisBall` class, you'll need to add a use statement at the top of the file just after it's own namespace definition.
### Enable PSR-4 auto-loading in your `composer.json` file
If you have namespaced your project and followed the PSR-4 convention, you have the option to enable PSR-4 auto-loading in your composer.json file.
Enabling PSR-4 auto-loading is optional. It will provide better auto-loading of your classes in your development environment and will future proof your code.
For example, let's say you have defined the following namespaces for the following folders:
*`App\Web` for your main application logic contained in `mysite/code`
*`App\SubModule` for a secondary module contained in `sub-module/code`
*`App\Web\Tests` for your application test suite contained in `mysite/tests`.
Your `autoload` section in your `composer.json` file should look like this:
Read the [Composer schema autoload documentation](https://getcomposer.org/doc/04-schema.md#autoload) for more information about configuring auto-loading in your project.
Note that applying a namespace to your project will also affect which template file SilverStripe tries to load when rendering certain objects.
For example, pretend you have a `RoadRunnerPage` class that extends `Page`. In SilverStripe 3, you would define a template for this page in `themes/example/templates/Layout/RoadRunnerPage.ss`. If you decide to move `RoadRunnerPage` to `App\Web\RoadRunnerPage`, you'll need to move the template to `themes/example/templates/App/Web/Layout/RoadRunnerPage.ss`.
This is a good point to commit your changes to your source control system before moving on to the next step.
## Step 4 - Update codebase with references to newly namespaced classes {#step4}
All core PHP classes in SilverStripe 4 have been namespaced. For example, `DataObject` is now called `SilverStripe\ORM\DataObject`. Your project codebase, config files and language files need be updated to reference those newly namespaced classes. This will include explicit references in your PHP code, but also string that contain the name of a class.
If you've opted to namespace your own code in the previous step, those references will need to be updated as well.
### Automatically update namespaced references with the `upgrade` command
If you've installed the upgrader, you can use the `upgrade` command to update references to namespaced classes.
The `upgrade` command will update PHP files, YML configuration files, and YML language files.
Each core SilverStripe 4 module includes a `.upgrade.yml` that defines the equivalent fully qualified name of each class. Most third party SilverStripe modules that have been upgraded to be compatible with SilverStripe 4, also include a `.upgrade.yml`. If you've namespaced your own project, you'll need to provide your own `.upgrade.yml` file . If you've used the upgrader to namespace your project, that file will have been created for you.
The `upgrade` command will try to update some strings that reference the old name of some classes. In some cases this might not be what you want. You can tell the upgrader to skip specific strings by using the `@skipUpgrade` flag in your PHPDoc comment. For example:
If you omit the `--write` flag you will get a preview of what change the upgrader will apply to your codebase. This can be helpful if you are tweaking your `.upgrade.yml` or if you are trying to identify areas where you should add a `@skipUpgrade` statement,
You can also tweak which rules to apply with the `--rule` flag: `code`, `config`, and `lang`. For example, the following command will only upgrade `lang` and `config` files:
The `upgrade` command can alter big chunks of your codebase. While it works reasonably well in most use cases, you should not trust it blindly. You should take time to review all changes applied by the `upgrade` command and confirm you are happy with them.
If you decide to update your namespace references by hand, you'll need to go through the entire code base and update them all from the old non-namespaced SilverStripe classes to the new namespaced equivalent. If you are referencing classes from third party modules that have been namespaced, you'll need to update those as well.
#### Update explicit references to classes in your code
Wherever your code explicitly references a SilverStripe class, it will need to be updated to the new namespaced equivalent. You can either update the reference to use the fully qualified name of the class or you can add a `use` statement to your file.
For example take the following SilverStripe 3 class. `DataObject` and `FieldList` need to point to their namespace equivalents.
`Image`, `BlogPost`, and `ProductService` represent classes. Those strings need to be updated to specify the full namespace.
The best way of achieving this is to use the [`::class` PHP magic class constant](http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.class.class) which will return the fully qualified name of a class.
Alternatively, you can spell out the full qualified name of each class in a string. For example, `'Image'` would become `'SilverStripe\\Assets\\Image'`. Note the use of the _double backslash_ — this is necessary because the backslash is an escape character.
#### Update references to classes in your YML config
YAML configuration files can reference SilverStripe classes. Those references also need to use the fully qualified name of each class.
Take for example the following SilverStripe 3 YAML configuration file.
#### Update references to classes in your language files
Translation keys are normally tied to classes. If you override SilverStripe's default translation or if you are localising your own project, you'll need to update those references to use the fully qualified name of each class.
For example, let's say you had the following translation file in `mysite/lang/eng.yml`.
DataObject database tables will default to use a namespaced name. For example, if you have a class under `App\Web\Products\ExplosiveTennisBall` that extends `DataObject`, the matching table in your database will be called `App_Web_Products_ExplosiveTennisBall`.
If your template files contain translatable strings, they also need to be updated to referenced the namespaced classes.
For example, `<%t Member.SINGULARNAME 'Member' %>` would become `<%t SilverStripe\Security\Member.SINGULARNAME 'Member' %>`.
Your codebase should now be referencing valid SilverStripe 4 classes. This means that your classes can be loaded at runtime. However, your codebase will still be using an outdated API.
This is a good point to commit your changes to your source control system before moving on to the next step.
## Step 5 - Updating your codebase to use SilverStripe 4 API {#step5}
This is the most intricate and potentially time-consuming part of the upgrade. It involves going through your entire codebase to remove references to deprecated APIs and update your project logic.
### Automatically update deprecated API references with the `inspect` command
The upgrader has an `inspect` command that can flag deprecated API usage, and in some cases, update your codebase to the SilverStripe 4 equivalent. This does require you to carefully review each change and warning to make sure the updated logic still work as intended. Even so, it is a huge time-saver compared to reviewing your code base manually.
Note that the `inspect` command loads your files with PHP interpreter. So basic syntax errors — for example, extending a class that does not exists — will cause an immediate failure. For this reason, you need to complete [Step 4 - Update codebase with references to newly namespaced classes](#step4) before running the `inspect` command.
```bash
upgrade-code inspect ./mysite/ --write
```
You can omit the `--write` flag if you just want to view the proposed changes without applying them. You can run the command on a specific subdirectory or file. This can be more manageable if you have a big project to go through.
Like the `upgrade` command, `inspect` gets its list of API changes from `.upgrade.yml` files. So you may get upgrade suggestions and substitution from third party modules. You can even include your own project specific changes in your `.upgrade.yml` if you want.
- Coyote.php:71 SilverStripe\ORM\DataObject->manyManyComponent(): DataObject->manyManyComponent() moved to DataObjectSchema. Access through getSchema(). You must manually add static::class as the first argument to manyManyComponent()
Changes not saved; Run with --write to commit to disk
If you're using a `.htaccess` file or `web.config` file to handle your server configuration, you can get the generic SilverStripe 4 version of those file from
Just like `index.php`, if you've modified your server configuration file from the one that shipped with SilverStripe 3, you'll need to reconcile your changes into the version retrieve from `recipe-core`.
[Refer to the installation instruction for your platform](/getting_started/installation/) if your server configuration is not managed via a `.htaccess` or `web.config` file.
### Finalising the entry point upgrade
At this stage, you could in theory run your project in SilverStripe 4.
This is a good point to commit your changes to your source control system before moving on to the next step.
* Run the following command `composer vendor-expose` to make static assets files accessible via the `public` directory.
If you are upgrading from SilverStripe 4.0 to SilverStripe 4.1 (or above), you'll need to update `index.php` before moving it to the public folder. You can get a copy of the generic `index.php` file from `vendor/silverstripe/recipe-core/public`. If you've made modifications to your `index.php` file, you'll need to replicate those into the new `public/index.php` file.
### Finalising the web root migration
You'll need to update your server configuration to point to the public directory rather than the root of your project.
Update your `.gitignore` file so `assets` and `_resources` (or `resources` if using a pre SilverStripe 4.4 release) are still ignored when located under the `public` folder.
This enables innovations like moving the SilverStripe module [vendor folder](/changelogs/4.0.0#vendor-folder) or the [public web root](/changelogs/4.1.0#public-folder).
If you have folders under `app` or `mysite` that need to be accessible for your project's web root, you need to say so in your `composer.json` file by adding an entry under `extra.expose`.
For example, let's say you have `scripts`, `images` and `css` folders under `app`. You can expose them by adding this content to your `composer.json` file:
```json
{
// ...
"extra": {
"branch-alias": {
"4.x-dev": "4.2.x-dev"
},
"expose": [
"app/scripts",
"app/images",
"app/css"
]
},
// ...
}
```
For the change to take affect, run the following command: `composer vendor-expose`.
Wherever you would have use a hardcoded path, you can now use the `path/to/file.css` syntax. To reference a static file from a module, prefix the path with the module's name (e.g.: `silverstripe/admin:client/dist/js/bundle.js`).
SilverStripe template files accept a similar format for referencing static assets. You will need to go through your assets files and remove hardcoded references.
## Step 10 - Update database class references {#step10}
If you've updated your class names to use namespaces you will need to reflect those changes in any existing database fields. For example, if you've renamed your `HomePage` class to `App\HomePage` then the database `ClassName` column needs to be updated to point to the `App\HomePage` class, otherwise the CMS will tell you that the page is obsolete. This also applies to polymorphic relationships.
There is no automated way to do this, but you can use the list generated in .upgrade.yml and copy it to `app/_config/legacy.yml`, removing any classes that don't extend DataObject.
```
SilverStripe\ORM\DatabaseAdmin:
classname_value_remapping:
HomePage: App\HomePage
```
This will automatically update affected columns when you first build the database.
## Step 11 - Running your upgraded site for the first time {#step11}
Your `img` and `a` tag references to your assets may now be pointing to a location in your assets folder that has been moved. There is a task available which will look through all your tables containing `HTMLText` and `HTMLVarchar` fields looking for broken references and then rewrite them to the new location of the file.
Some third party modules may include their own migration tasks. Take a minute to consult the release notes of your third party dependencies to make sure you haven't missed anything.