Upgrading to Craft 3.6

Craft 3.6 introduced a few changes to be aware of.

PHP 7.2 #

Craft 3.6 requires PHP 7.2.5 or later, while previous versions of Craft 3 required PHP 7.0 or later.

System Report PHP Version

Find which PHP version an environment is running from the control panel under UtilitiesSystem Report.

If any of your environments are running PHP 7.0.x or 7.1.x, you may need to speak to your hosting company to get PHP upgraded. (We recommend using PHP 7.4 for the time being.)

You’ll also need to check your composer.json file’s config.platform.php value, which should be set to the minimum PHP version in use across all of your environments. See Resolving PHP Requirement Conflicts for more info.

Interactive migrate/all command #

The migrate/all command now outputs all pending migrations, and if the shell is interactive, it will prompt the user for confirmation before running them (just like migrate/up). This change doesn’t affect most deployment tools, as they will typically run terminal commands via non-interactive shells, however that’s not always the case.

If you find that migrations aren’t getting run during deployment, add the --interactive=0 flag to your command. For example, if you’re running migrate/all from Composer’s post-install-cmd event, change it to this in composer.json:

  "scripts": {
    "post-install-cmd": [
      "@php craft migrate/all --interactive=0"

HTML File Uploads #

The allowedFileExtensions config setting no longer includes htm or html file extensions by default due to security concerns. If your site needs to allow HTML file uploads, you can add those extensions back via the extraAllowedFileExtensions config setting.

'extraAllowedFileExtensions' => ['htm', 'html'],

Deprecated Config Settings #

The siteName and siteUrl config settings have been deprecated. We strongly recommend you set your sites’ names and URLs using environment variables instead.

Site URL setting with an environment variable

We’ve also deprecated the purgeUnsavedDraftsDuration config setting, as Craft has no use for it anymore with its new entry creation workflow.

Index and Foreign Key Names #

Index and foreign key names generated by Craft are now completely random. If you have any module or plugin migrations that remove indexes or foreign keys, ensure that they are using MigrationHelper::dropIndexIfExists() and dropForeignKeyIfExists(), rather than $this->dropIndex() and $this->dropForeignKey().

// Bad:
$this->dropIndex($this->db->getIndexName($table, $columns, $unique), $table);
$this->dropForeignKey($this->db->getForeignKeyName($table, $columns), $table);

// Good:
use craft\helpers\MigrationHelper;

MigrationHelper::dropIndexIfExists($table, $columns, $unique, $this);
MigrationHelper::dropForeignKeyIfExists($table, $columns, $this);

Field Type Accessibility #

Plugin developers have a couple ways to make their field types more accessible:

  • If the field type’s inputHtml() method returns multiple HTML inputs, they can now override the new useFieldset() method so their input HTML is wrapped in a <fieldset> rather than a <div>, and their field name is wrapped in a <legend> rather than a <label>.

    public function useFieldset(): bool
        return true;
  • The field type’s HTML input(s) can now set an aria-describedby attribute, set to the field handle followed by -instructions (e.g. aria-describedby="fieldHandle-instructions"), which will point screen reader users to the field’s instructions text when focused.

Both changes can be made without explicitly bumping your plugin’s craftcms/cms requirement in composer.json; they just won’t have any effect on earlier versions of Craft.

Guzzle 7 #

Composer will start pulling in Guzzle 7 if all plugins and other dependencies support it. If you maintain a plugin that requires Guzzle 6, you should work to support Guzzle 7 for its PHP 8 support.

Testing #

If you have any custom test fixtures that extended craft\test\fixtures\elements\ElementFixture, they will need to be updated to extend one of the new base fixture classes:

  • If you were using ElementFixture to create elements, use craft\test\fixtures\elements\BaseElementFixture instead.
  • If you were using ElementFixture to set content for existing elements (such as Single section entries or global sets which are part of the project config), use craft\test\fixtures\elements\BaseContentFixture instead.

For simple use cases, a fixture that extends BaseElementFixture needs only to override the createElement() method:

protected function createElement(): ElementInterface
    return new MyElement();

Craft’s built-in base element fixture classes – AssetFixture, CategoryFixture, EntryFixture, GlobalSetFixture, TagFixture, and UserFixture – have each been updated to extend BaseElementFixture.

Redis Mutex #

If you’re overriding the mutex component from config/app.php and setting it to yii\redis\Mutex, you may need to start setting yii\redis\Connection::$retries to 1 in the main redis component config:

return [
    'components' => [
        'redis' => [
            'class' => yii\redis\Connection::class,
            'retries' => 1,
            // ...

Custom Session Drivers #

If your project is overriding the session component in config/app.php with a custom session driver, you’ll need to review the Yii 2.0.39 upgrade notes to ensure compatibility with Yii 2.0.39.

If you’re using a session driver package such as yii2-redis, make sure that you’re running its latest version.

Applies to Craft CMS 3.