Skip to content Skip to footer navigation
You are reading the Statamic 6 Alpha docs. 👀

Upgrade from 5 to 6

A guide for upgrading from 5 to 6. For most sites (those running Laravel > 10), the process will take less than 5 minutes.

Overview

First read through this guide to see if there's anything that you might need to adjust. While there are many items on this page, a majority of them only apply to addons or custom code. We've noted who each item would apply to so you can more easily scan through the changes.

Upgrade using Composer

In your composer.json, change the statamic/cms requirement:

-"statamic/cms": "^5.0"
+"statamic/cms": "^6.0"

Then run:

composer update statamic/cms --with-dependencies

High impact changes

PHP and Laravel support

Affects apps using PHP < 8.2 or Laravel < 11.

  • The minimum version of PHP is now 8.2.
  • The minimum version of Laravel is now 11.

We highly recommend upgrading all the way to Laravel 12 and PHP 8.4.

Hot Tip!

If you want to (semi-)automate the Laravel upgrade process, we recommend using Laravel Shift (use that link for a special 19.83% discount 🤘).

A troll pointing a teaching stick

Vue 3

Affects apps or addons that use Vue.

We have upgraded the Control Panel's version of Vue.js from 2 to 3.

To keep this upgrade guide manageable, we have a dedicated page for upgrading from Vue 2 to Vue 3.

If you do not have any custom Vue components in your app, or in your own addons, you can skip this.

Timezones

Affects apps using dated collections or date fields

If your timezone setting in config/app.php is set to UTC, then nothing will change for you.

Dates remain stored in your application's timezone. But now Statamic will convert them to UTC at runtime, which makes it much easier for Statamic to localize them as needed.

This applies to dated entries or date fields.

For example, if you have your timezone set to New York (GMT-5:00) and you have a date at 10pm, when it gets converted to UTC it will be 5 hours ahead - in the next day!

// config/app.php
'timezone' => 'America/New_York',
# an-entry.md
my_date_field: '2025-03-06 22:00'
$entry->my_date_field;
-// 5.x: Carbon { 2025-03-06 22:00 America/New_York }
+// 6.x: Carbon { 2025-03-07 03:00 UTC }
{{ my_date_field | iso_format('JJJJ') }}
{{ Statamic::modify($my_date_field)->iso_format('JJJJ') }}
-5.x: Thursday, March 6, 2025 10:00 PM
+6.x: Friday, March 7, 2025 3:00 AM

It's best practice to keep dates as UTC until you're ready to display them, which means modifiers will deal with UTC versions. But, you can opt into automatic conversion to your display timezone by changing the following in config/statamic/system.php:

+'localize_dates_in_modifiers' => true,

This settings should have been automatically set to true by Statamic during the upgrade, but you should confirm it.

Control Panel

Dates in the Control Panel are now localized to the user's operating system timezone, rather than the application timezone.

For example, on Statamic 5, if you were in a different timezone to what your app was configured in, and you select a date from the date picker, that date would be treated as the date for the app's timezone. Not your timezone.

This was a common cause of confusion, which was one of the main reasons for all these changes.

Now in Statamic 6, the date you pick will be the date in your timezone.

There is nothing for you to change except your expectations when working with dates, and instructing your clients about it.

REST API & GraphQL

Dates will now be returned by Statamic's REST API and GraphQL API in UTC, allowing you to localize them as needed on your frontend.

Changing your app timezone

It's best practice to set your app's timezone to UTC. However, changing the timezone in an existing project is a big undertaking and could mean lots of content and dates need to be updated.

Statamic 6 does not require that you change your timezone to UTC. But if you want to, we have provided a way to automate it.

Read how to change your timezone to UTC.

Medium impact changes

Carbon 3

Support for Carbon 2.x has been removed. All Statamic 6 sites now require Carbon 3.x.

If you're using any of Statamic's months_ago, weeks_ago, days_ago, hours_ago, minutes_ago, and seconds_ago modifiers, you will notice that they now return floats instead of integers. Comparing against past timestamps will also result in negative numbers.

You may need to updates your templates to account for these changes.

Globals

We have made various changes to how globals are stored and localized. If you use globals in your app, please read through these changes and take any necessary action.

Single site installs: Variables are now stored separately from the global set config

Global Variables are now stored separately from the global set's config, allowing config and content to be properly separated.

Instead of living under a data key in the global set's YAML file, they now live in a separate YAML file in a directory named after your default site, usually called default.

Before:

# content/globals/seo.yaml
title: SEO
data:
meta_description: Synthwave nostalgia with soaring sax and heartfelt vibes.
meta_image: the-midnight.jpg

After:

# content/globals/seo.yaml
title: SEO
# content/globals/default/seo.yaml
meta_description: Synthwave nostalgia with soaring sax and heartfelt vibes.
meta_image: the-midnight.jpg

This change may have been performed automatically by Statamic during the upgrade process.

Note: This change doesn't affect multi-sites or sites storing global variables in the database, since they're already stored separately.

Multi-sites: Localized sites are now determined by the sites array

Previously, when you configured the sites a global set was localized into, it created the global variable files for you, then used the existence of those files to determine which sites the global set was localized into.

Now, Statamic will use the sites array in the global set's config file to determine which sites the global set is localized into, as well as mapping the origins for localizations.

# content/globals/seo.yaml
title: SEO
sites:
en: null
fr: en # Localized from en
de: null # No origin

This change may have been performed automatically by Statamic during the upgrade process.

Note: This change doesn't affect single-site installs.

Events

Previously, when saving global variables in the Control Panel, the entire global set would have been saved, causing the GlobalSetSaving, GlobalSetCreated and GlobalSetSaved events to be dispatched. However, now, only the global variable itself will be saved.

This means that if you were listening to any of these events to pick up changes to global variables, you should instead listen for the GlobalVariablesSaving, GlobalVariablesCreated and GlobalVariablesSaved events.

Removed methods on GlobalSet class

The addLocalization and removeLocalization methods have been removed from the GlobalSet class.

If you were calling these methods in your app, you should update your code to call save and delete on the Variables class instead.

-$globalSet->addLocalization($globalSet->makeLocalization('en')->data(['foo' => 'bar']));
-$globalSet->removeLocalization('en');
+$globalSet->in('en')->data(['foo' => 'bar'])->save();
+$globalSet->in('en')->delete();

Breadcrumbs

Affects apps or addons displaying breadcrumbs in the Control Panel.

Breadcrumbs are now generated from items in the Control Panel navigation, rather than needing to be passed into views manually.

You should remove references to the Breadcrumb class in your code, as well as the <breadcrumbs> Vue component.

-use Statamic\CP\Breadcrumbs;
-
-$crumbs = Breadcrumbs::make([
- ['text' => 'First', 'url' => '/first'],
- ['text' => 'Second', 'url' => '/second'],
-]);
-
-return view('myview', ['crumbs' => $crumbs]);
+return view('myview');
-<breadcrumbs :crumbs='@json($crumbs)'></breadcrumbs>
<template>
- <breadcrumbs :crumbs="crumbs" />
</template>
<script>
export default {
data()
return {
- crumbs: [
- ['text' => 'First', 'url' => '/first'],
- ['text' => 'Second', 'url' => '/second'],
- ]
]
}
}
</script>

To learn more about customizing breadcrumbs, please refer to the CP Navigation documentation.

Starter Kits: Removed export_as option

Affects starter kits using the export_as option.

The export_as option has been removed in favor of the new package folder convention, which makes dealing with multiple README.md files easier, for example.

Low impact changes

Added columns to the users table

Affects apps storing users in the database.
If you're storing users in the database, you will need to add three columns to the users table in order to support Statamic's two-factor authentication feature. You can add the columns using a migration:

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->text('two_factor_secret')->nullable();
$table->text('two_factor_recovery_codes')->nullable();
$table->timestamp('two_factor_confirmed_at')->nullable();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn(['two_factor_secret', 'two_factor_recovery_codes', 'two_factor_confirmed_at']);
});
}
};

You can run the migration by running php artisan migrate.

You should also add a cast for the two_factor_confirmed_at column in your User model:

protected function casts(): array
{
return [
'email_verified_at' => 'datetime',
'preferences' => 'json',
+ 'two_factor_confirmed_at' => 'datetime',
];
}

This change may have been performed automatically by Statamic during the upgrade process.

Moment.js has been removed

Affects addons and custom code directly using moment.js
If you are using moment.js you should replace it with an alternative. We suggest using native JS code which should be enough these days. For example:

-moment().seconds();
+new Date().getSeconds();

You should search for moment or $moment references in your code and replace appropriately.

Here is a good resource on how to migrate away from Moment.js.

Glide 3

Statamic is now using Glide 3, which uses intervention/image 3.x under the hood.

In most cases, you shouldn't notice any difference, however, if you have a custom manipulator, it will need to be updated. Please refer to the Glide 3 changelog for more information.

Wildcard tags

Affects apps using the {{ session }}, {{ cookie }}, {{ nav }} and {{ redirect }} tags.

In previous versions of Statamic, these tags accepted a wildcard value, allowing you to pass a handle or key directly:

{{ session:foo }}

Here, foo is the wildcard value. However, if a variable named foo existed in the template’s context, its value would be used instead of the literal string "foo", potentially causing unintended behaviour.

In Statamic 6, wildcard values are always treated as literal strings. If you need to pass a variable dynamically, you should use the appropriate parameter instead:

{{ session :handle="foo" }}

This ensures that foo is interpreted as a variable rather than a fixed string.

Site methods

Affects addons using the Site::setConfig() method.

The Site::setConfig() method was deprecated in Statamic 5. It has now been removed. You should use the Site::setSites() method instead:

-Site::setConfig([
- 'sites' => [
- 'english' => ['name' => 'English', 'locale' => 'en_US', 'url' => '/en'],
- 'french' => ['name' => 'French', 'locale' => 'fr_FR', 'url' => '/fr'],
- ],
-]);
+Site::setSites([
+ 'english' => ['name' => 'English', 'locale' => 'en_US', 'url' => '/en'],
+ 'french' => ['name' => 'French', 'locale' => 'fr_FR', 'url' => '/fr'],
+]);

CP Nav Items: ->active() method removed

Affects apps or addons adding nav items to the Control Panel.

When adding nav items to the Control Panel, it was previously possible to specify a regex pattern used to determine if the nav item was active. However, after some improvements in Statamic, this method is no longer needed and has been removed after a deprecation period. You can safely remove it from your nav items:

Nav::extend(function ($nav) {
$nav->create(ucfirst($type))
->section('SEO')
->route("ecommerce.orders.index")
- ->active("ecommerce/orders")
->icon($defaults->first()['type_icon']);
});

statamic cache driver has been removed

Affects apps or addons using the statamic cache driver.

The statamic cache driver has been removed. If you were using it, you should switch to the file cache driver instead.

// config/cache.php
-'driver' => 'statamic',
+'driver' => 'file',

Entry::addLocalization() method removed

Affects apps or addons using the Entry::addLocalization() method.

The Entry::addLocalization() method has been removed. If you were using it, you should now use the Entry::makeLocalization() method instead.

-$entry->addLocalization($entry);
+$entry->makeLocalization('german');

ApiController::filterSortAndPaginate() method renamed

Affects apps or addons providing custom API endpoints.

The filterSortAndPaginate() method on the ApiController class has been renamed to updateAndPaginate().

-$this->filterSortAndPaginate($query);
+$this->updateAndPaginate($query);

Relate tag has been removed

The relate tag left over from Statamic 2 has been removed. You can safely remove it and rely on augmentation instead.

-{{ relate:products }}
- {{ title }}
-{{ /relate:products }}
+{{ products }}
+ {{ title }}
+{{ /products }}

docs-callout partial has been replaced

Affects apps or addons with custom Blade views in the Control Panel.

Statamic's docs-callout partial has been replaced with a Blade component of the same name. If you were using this partial in your custom Blade views, you should update your code to use the component instead.

Before:

@include(
'statamic::partials.docs-callout',
[
'topic' => __('Blueprints'),
'url' => Statamic::docsUrl('blueprints'),
]
)

After:

<x-statamic::docs-callout
:topic="__('Blueprints')"
:url="Statamic::docsUrl('blueprints')"
/>

Section fieldtype has been deprecated

The Section fieldtype has been deprecated and will be removed in Statamic 7. We recommend using sections in the blueprint builder instead.

urlencode and rawurlencode modifiers now encode forward slashes

Affects apps or addons using the urlencode or rawurlencode modifiers.

The urlencode and rawurlencode modifiers now encode forward slashes (/). If you were relying on forward slashes not being encoded, you can use the urlencode_except_slashes and rawurlencode_except_slashes modifiers instead.

{{ my_string | urlencode }} // [tl! --]
{{ my_string | urlencode_except_slashes }} // [tl! ++]
{{ my_string | rawurlencode }} // [tl! --]
{{ my_string | rawurlencode_except_slashes }} // [tl! ++]

Zero impact changes

...