Overview
First read through this guide to see if there's anything that you might need to adjust. When upgrading, Statamic may automate some things for you. They'll be noted below.
In your composer.json
, change the statamic/cms
requirement:
"statamic/cms": "3.3.*"
Then run:
composer update statamic/cms --with-dependencies
High impact changes
PHP >=7.4 required
Statamic 3.3 now requires at least PHP 7.4.
If you're running a lower version, we recommend upgrading all the way to 8.1.
Laravel 8 required
Statamic 3.3 now requires at least Laravel 8.
If you're running a lower version, we recommend upgrading all the way to 9.
You can check your version of Laravel by running php artisan -V
.
Find out how to upgrade from Laravel 7 to Laravel 8.
Medium impact changes
Entries fieldtype augments to query builders
The entries
fieldtype would previously augment to an EntryCollection
of Entry
objects. In 3.3, they will augment to a query builder.
In Antlers
If you were adding modifiers to your loop, you'll need to apply them to an inner aliased loop.
Before:
{{ related_posts modifier="param" }} ...{{ /related_posts }}
After:
{{ related_posts as="whatever" }} {{ whatever modifier="param" }} ... {{ /whatever }}{{ /related_posts }}
In PHP
If you're using them in PHP, you'll need to add a ->get()
to grab the entries from the query before continuing.
Before:
$relatedPosts->someCollectionMethod(...);
After:
$relatedPosts->get()->someCollectionMethod(...);
Low impact changes
New Experimental Antlers Parser
3.3 includes an overhauled Antlers parser. It fixes many issues with the existing parser and brings many new features.
By upgrading to 3.3 you will not automatically get the new parser.
If you'd like to use the new parser, read about it in the docs, where it explains the experimental nature and how to use it.
Date field's time_required setting has been removed
The time_required
option has been removed from the date
fieldtype.
The time_enabled
setting still exists, and we suggest you use that.
v-calendar upgraded to v2
If you were relying on the v-calendar package within the Control Panel, be aware that it has been upgraded to v2.
Property access on items now performs augmentation
See PR #5297 for more details.
Previously if you were to do $entry->something
, it would get the raw value on the entry. It would not factor in fallbacks from any origin entries, or the collection's injected data. It would not do any augmentation. It would not give you method-based values you might expect automatically in templates (like id
, slug
, etc).
In 3.3, doing $entry->something
will do all of those. It will factor in fallbacks, augment, and give you method based values.
id: 123intro: 'hello' # (a "text" fieldtype)foo: 'bar' # (not even in the blueprint at all)content: | # (a "markdown" fieldtype) # Heading Paragraph
// 3.2$entry->content; // "# Heading\nParagraph"$entry->intro; // "hello"$entry->foo; // "bar"$entry->id; // null$entry->slug; // null$entry->url; // null // 3.3$entry->content; // "<h1>Heading</h1><p>Paragraph</p>$entry->intro; // "hello"$entry->foo; // "bar"$entry->id; // 123$entry->slug; // "my-entry"$entry->url; // "/blog/my-entry"
On 3.2, property access on terms did nothing. You'd get a warning and null.
Augmentation methods return Value instances
See PR #5302 for more details. This change will only affect custom PHP code.
This is considered a low impact change since it should only affect edge cases.
- If you were explicitly coding something expecting a non-
Value
, it will now be aValue
. - If it was being cast to a string or array, no change is needed since the
Value
class knows how to cast itself.
For example, previously toAugmentedArray()
you'd only get Value
objects for fields that exist in the blueprint.
$arr = $entry->toAugmentedArray();// [// 'published' => false,// 'url' => '/blog/my-post'// 'some_blueprint_field' => Value('some value'),// ...// ] $inBlog = (Str::startsWith($arr['url'], '/blog')) ? 'yes' : 'no'; // yes$isPublished = ($arr['published']) ? 'yes' : 'no'; // 'no'
In 3.3, everything in the array would be wrapped in Value
objects.
$arr = $entry->toAugmentedArray();// [// 'published' => Value(false),// 'url' => Value('/my-post')// 'some_blueprint_field' => Value('some value'),// ...// ] // ✅ No change. It would cast the Value to a string, giving you the same outcome.$inBlog = (Str::startsWith($arr['url'], '/blog')) ? 'yes' : 'no'; // yes // 🚨 This is changing.// Previously it would check "if true/false". But now it's "if object" which will always be true.$isPublished = ($arr['published']) ? 'yes' : 'no'; // 'yes'
You'll now need to add ->value()
to get the underlying value.
$isPublished = ($arr['published']->value()) ? 'yes' : 'no'; // 'yes'
The same goes for other augmentation methods:
-
$entry->toAugmentedArray()
will only containValue
instances. -
$entry->toAugmentedCollection()
will only containValue
instances. -
$entry->augmentedValue('field')
will always return aValue
instance. -
$entry->augmented()->get('field')
will always return aValue
instance.
But really, the fix would be to avoid the manual augmentation methods entirely and just do $entry->fieldname
, $entry->published
, etc.
$isPublished = ($entry->published) ? 'yes' : 'no'; // 'yes'
Form submission data is an unfiltered collection
In 3.2, if you did $submission->data()
you would sometimes get an array, sometimes an Illuminate\Support\Collection
(the inconsistency was a bug) and any keys that didn't exist in the blueprint would get filtered out.
In 3.3, you will always get a Collection, and it will not have any filtering applied.
Live Preview
If you're not overriding the toLivePreviewResponse
in the Entry
or Term
classes, there is no change for you.
The toLivePreviewResponse
methods have been removed in favor of a token based system. You can instead migrate to a dedicated route that will get the Live Preview version of the entry/term via a token.
See the Live Preview Custom Rendering docs for how to do this.
Custom date fields are now Carbon instances
Custom date fields are now stored in the Stache as Carbon
instances.
This will only affect you if you're performing a query on a date
field expecting it to be a string. For instance, $query->where('datefield', 'like', '2020-%')
or :datefield:starts_with="2020"
The actual date
field on an entry (i.e. the publish date) would have already been a Carbon instance. This only applies to date
fields that aren't named date
.
Grids, Replicators, and Bards augment differently
Previously, these fields all augment to arrays containing arrays for each row or set.
In 3.3, it will be an array of Values
instances representing each row or set.
In your templates there will be no changes. There's only a change necessary if you are writing PHP and expecting those to be arrays. You can get the underlying array by doing $row->all()
.
Commonmark 2 is supported
Laravel 8 and Statamic 3.3 now support both CommonMark 1 or 2. When you do a composer update
, Composer will try to install the latest available version, which may be v2.
If you have any custom Markdown extensions you will need to either:
- upgrade them for Commonmark 2
-
or you may require
league/commonmark ^1.6
in your project.
If you don't have any custom extensions, the switch from Commonmark v1 to v2 should make no difference to you.
Control panel forms now only submit visible fields
Control Panel forms now only submit visible fields (as originally intended) which fixes sometimes
/ required_if
/ etc. validation rules, among other things.
This could potentially be a breaking change if you were using field conditions purely for cosmetic showing/hiding of form fields, in which case we might recommend using the revealer fieldtype.
Read more: Conditional Fields Data Flow
Zero impact changes
These are items that you can completely ignore. They are suggestions on how to improve your code using newly added features.
You probably don't need to manually augment
If you were manually grabbing an augmented value instance, then getting the actual augmented value from that - you can now just use the magic getters to get the underlying augmented value.
$entry->augmentedValue('fieldname')->value(); $entry->fieldname;
Leverage relationship magic methods
If you were manually performing a new query based on selections from an entries fieldtype, you can now use the magic method to get a query builder.
$relatedIds = $entry->get('related_posts'); $selectedFeaturedEntries = Entry::query()->whereIn('id', $relatedIds)->where('featured', true)->get(); $selectedFeaturedEntries = $entry->related_posts()->where('featured', true)->get();
Use Tags in Blade
If you were using the Blade Directives addon to work with Statamic data in your Blade templates, you can now use a whole bunch of native features instead.
@collection('pages', ['title:is' => 'My Title', 'author:is' => 'Erin', 'limit' => 3, 'sort' => 'title:desc']) @foreach (Statamic::tag('collection:pages') ->params(['title:is' => 'My Title', 'author:is' => 'Erin']) ->limit(3)->sort('title:desc') as $entry) @if($entry['no_results']) @if($entry->no_results) <p>There are no results</p> @else {{ $entry['title'] }} {{ $entry->title }} @endif@endcollection
return [ 'providers' => [ Edalzell\Blade\Augmentation\AugmentationViewServiceProvider::class, Illuminate\View\ViewServiceProvider::class, ]]