# Upgrade from 5 to 6

A guide for upgrading from 5 to 6. For most sites (those running Laravel >= 12), 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:

```json
"statamic/cms": "^5.0" // [tl!--]
"statamic/cms": "^6.0" // [tl!++]
```

Then run:

``` shell
composer update statamic/cms --with-dependencies
```

## High impact changes

### PHP and Laravel support
**Affects apps using PHP < 8.3 or Laravel < 12.**

- The minimum version of PHP is now 8.3.
- The minimum version of Laravel is now 12.

We highly recommend upgrading all the way to Laravel 13 and PHP 8.5.

:::tip
If you want to (semi-)automate the Laravel upgrade process, we recommend using [Laravel Shift](https://laravelshift.com/discounts/statamic-1983) (use that link for a special 19.83% discount 🤘).
:::

### 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](/upgrade-guide/vue-2-to-3.md).

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!

```php
// config/app.php
'timezone' => 'America/New_York',
```
```yaml
# an-entry.md
my_date_field: '2025-03-06 22:00'
```
```php
$entry->my_date_field;
// 5.x: Carbon { 2025-03-06 22:00 America/New_York } [tl! --]
// 6.x: Carbon { 2025-03-07 03:00 UTC } [tl! ++]
```

::tabs
::tab antlers
```antlers
{{ my_date_field | iso_format('JJJJ') }}
5.x: Thursday, March 6, 2025 10:00 PM {{# [tl! --] #}}
6.x: Friday, March 7, 2025 3:00 AM {{# [tl! ++] #}}
```
::tab blade
```blade
{{ Statamic::modify($my_date_field)->iso_format('JJJJ') }}
5.x: Thursday, March 6, 2025 10:00 PM {{-- [tl! --] --}}
6.x: Friday, March 7, 2025 3:00 AM {{-- [tl! ++] --}}
```
::

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`:

```php
'localize_dates_in_modifiers' => true, // [tl! ++] 
```

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

For more information on how Timezones work in Statamic 6, please see the [Timezones guide](/knowledge-base/tips/timezones.md).

#### 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](/tips/change-timezone-to-utc.md).

## Medium impact changes

### Carbon 3

Support for [Carbon 2.x](https://carbon.nesbot.com/docs/) has been removed. All Statamic 6 sites now require [Carbon 3.x](https://carbon.nesbot.com/docs/#api-carbon-3).

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:**
```yaml
# content/globals/seo.yaml

title: SEO
data:
  meta_description: Synthwave nostalgia with soaring sax and heartfelt vibes.
  meta_image: the-midnight.jpg
```

**After:**
```yaml
# content/globals/seo.yaml

title: SEO
```

```yaml
# 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.

```yaml
# 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`](https://statamic.dev/extending/events#globalvariablessaving), [`GlobalVariablesCreated`](https://statamic.dev/extending/events#globalvariablescreated) and [`GlobalVariablesSaved`](https://statamic.dev.test/extending/events#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.

```php
$globalSet->addLocalization($globalSet->makeLocalization('en')->data(['foo' => 'bar'])); // [tl! remove]
$globalSet->removeLocalization('en'); // [tl! remove]

$globalSet->in('en')->data(['foo' => 'bar'])->save(); // [tl! add]
$globalSet->in('en')->delete(); // [tl! add]
```

### Search: `'searchables' => 'all'`
**Affects apps using `'searchables' => 'all'` in their search config.**

Previously, you could set `'searchables' => 'all'` on a search index to include entries, terms, assets, users and anything provided by [custom searchables](/frontend/search.md#custom-searchables).

However, in v6, to split out search between the frontend and the Control Panel, support for `'searchable' => 'all'` has been removed.

You can now either use `'searchables' => 'content'` - which includes entries, terms and assets (**not** users) - or explicitly list [the searchables](/frontend/search.md#searchables) you want:

```php
// config/statamic/search.php

'indexes' => [  
  
    'default' => [  
        'driver' => 'local',  
        'searchables' => ['collection:blog', 'taxonomy:categories', 'assets:*'],  
        'fields' => ['title'],  
    ],
    
],
```

We’ve avoided automating this migration so you can intentionally decide whether users should be included.

### 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.

``` php
use Statamic\CP\Breadcrumbs; // [tl! remove:start]

$crumbs = Breadcrumbs::make([
    ['text' => 'First', 'url' => '/first'],
    ['text' => 'Second', 'url' => '/second'],
]);

return view('myview', ['crumbs' => $crumbs]);// [tl! remove:end]
return view('myview'); // [tl! add]
```

``` blade
<breadcrumbs :crumbs='@json($crumbs)'></breadcrumbs> {{-- [tl! remove] --}}
```

``` vue
<template>
    <breadcrumbs :crumbs="crumbs" /> <!-- [tl! remove] -->
</template>
<script>
export default {
    data()
        return {
            crumbs: [ // [tl! remove:start]
                ['text' => 'First', 'url' => '/first'],
                ['text' => 'Second', 'url' => '/second'],
            ] // [tl! remove:end]
        ]
    }
}
</script>
```

To learn more about customizing breadcrumbs, please refer to the [CP Navigation documentation](/extending/cp-navigation.md#breadcrumbs).

### 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](/starter-kits/creating-a-starter-kit.md#the-starter-kit-package), which makes dealing with multiple README.md files easier, for example.

### Custom Icons

If you are using any `icon` fieldtypes with the `directory` option, you will need to register your icon set and reference the set name instead.

```php
// AppServiceProvider.php
use Statamic\Facades\Icon; // [tl! ++]

public function boot(): void
{
    Icon::register('heroicons', base_path('resources/heroicons')); // [tl! ++]
}
```

```yaml
-
  handle: favourite_icon
  field:
    type: icon
    directory: resources/heroicons # [tl! --]
    set: heroicons # [tl! ++]
```

If you are using custom icons for your Replicator or Bard sets, the method changed:

```php
use Statamic\Fieldtypes\Sets;

Sets::setIconsDirectory(directory: 'path/to/heroicons'); // [tl! --]
Sets::useIcons('heroicons', 'path/to/heroicons'); // [tl! ++]
```

Or if you need to do both, you can reference the set name:

```php
Icon::register('heroicons', base_path('resources/heroicons'));
Sets::useIcons('heroicons');
```

### Bard: `inline: break`
**Affects apps using `inline: break` on Bard fields.**

We've simplified the `inline` config option on Bard fields. It is now a toggle, as opposed to a select dropdown with various modes.

If you were using the `inline: break` option, you should use the new `inline_hard_breaks` option instead:

```yaml
inline: break # [tl! --]
inline: true # [tl! ++]
inline_hard_breaks: true # [tl! ++]
```

### Custom Control Panel Pages
**Affects apps or addons with custom Control Panel pages.**

If your app or addon includes custom Control Panel pages, we recommend migrating them to Vue with [Inertia.js](https://inertiajs.com/) for the best experience. This provides SPA-style page transitions and a more consistent experience alongside the rest of the Control Panel. See the [CSS & JavaScript](/control-panel/css-javascript.md#inertia) page for more details.

For simpler addons, or if you prefer not to use Vue, you may continue to build Control Panel pages using Blade, but there are a few limitations to be aware of:

- Blade-rendered pages trigger a full page reload rather than the SPA-style transitions used elsewhere in the Control Panel.
- Under the hood, Blade views are rendered inside a Vue component, which means `<script>` tags are not supported within your views.

Statamic 6 ships with a growing set of [Control Panel UI components](https://ui.statamic.dev). To help your pages feel more native, you may want to integrate these components where possible.

### Custom Utilities
**Affects apps or addons with custom utilities.**

Utilities may now [return Inertia.js components](/control-panel/utilities.md#creating-a-utility) instead of Blade views, by replacing `->view()` with `->inertia()`:

```php
$utility
    ->view('my-utility', fn ($request) => ['foo' => 'bar']) // [tl! --]
    ->inertia('my-addon/MyUtility', fn ($request) => ['foo' => 'bar']) // [tl! ++]
```

Utilities that use Blade will continue to work without any changes. However, the limitations mentioned above for custom Control Panel pages also apply to utilities.

If your Blade view uses `@extends('statamic::layout')`, you can remove the layout wrapper:

``` blade
@extends('statamic::layout') {{-- [tl! --] --}}

@section('content') {{-- [tl! --] --}}
    <div>...</div>
@endsection {{-- [tl! --] --}}
```

## Low impact changes

### Database users
**Affects apps that store users in the database.**

During the upgrade process, Statamic will attempt to publish two database migrations: 

- One to add columns to the `users` table to support [two-factor authentication](/users.md#two-factor-authentication)
- One to create a `webauthn` table for [passkeys](/users.md#passkeys)

Run `php artisan migrate` to apply them. 

You should also add a cast for the new `two_factor_confirmed_at` column on your `User` model:

```php
protected function casts(): array  
{  
    return [  
        'email_verified_at' => 'datetime',  
        'preferences' => 'json',  
        'two_factor_confirmed_at' => 'datetime',  // [tl! add]
    ];  
}
```

#### Migrations aren't published
If the migrations aren't published automatically, please follow these steps:

1. Generate the auth migrations:
    ```php
    php please auth:migration
    ```
   This creates two migrations. You can safely delete the `update_users_table` migration.
2. Create a migration to add the required columns to the `users` table:
    ```php
    <?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']);  
            });  
        }
    };
    ```
3. Run the migrations:
    ```php
    php artisan migrate
    ```
### 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:

```js
moment().seconds(); // [tl! --]
new Date().getSeconds(); // [tl! ++]
```

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

[Here is a good resource](https://github.com/you-dont-need/You-Dont-Need-Momentjs) 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](https://glide.thephpleague.com/3.0/changelog/) for more information.

### Algolia

Statamic now requires v4 of the `algolia/algoliasearch-client-php` package. 

If you interact with this package directly, please [refer to its changelog](https://github.com/algolia/algoliasearch-client-php/blob/main/CHANGELOG.md) to review any changes that may affect your code.

### 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:

```antlers
{{ 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:

```antlers
{{ session :handle="foo" }}
```

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

### Removed methods

The following methods have been removed in Statamic 6.

#### `Site::setConfig()`

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

```php
Site::setConfig([ // [tl! remove:5]
    'sites' => [
        'english' => ['name' => 'English', 'locale' => 'en_US', 'url' => '/en'],
        'french' => ['name' => 'French', 'locale' => 'fr_FR', 'url' => '/fr'],
    ],
]);

Site::setSites([ // [tl! add:3]
    'english' => ['name' => 'English', 'locale' => 'en_US', 'url' => '/en'],
    'french' => ['name' => 'French', 'locale' => 'fr_FR', 'url' => '/fr'],
]);
```

#### `NavItem::active()`

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:

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

#### `Entry::addLocalization()`

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

```php
$entry->addLocalization($entry); // [tl! --]
$entry->makeLocalization('german'); // [tl! ++]
```

#### `ApiController::filterSortAndPaginate()`

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

```php
$this->filterSortAndPaginate($query); // [tl! --]
$this->updateAndPaginate($query); // [tl! ++]
```

### `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.

```php
// config/cache.php

'driver' => 'statamic',  // [tl! --]
'driver' => 'file', // [tl! ++]
```

### 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](/augmentation.md) instead.

```antlers
{{ relate:products }} {{# [tl! remove:2] #}}
    {{ title }} 
{{ /relate:products }}

{{ products }} {{# [tl! add:2] #}}
    {{ 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 Vue component. If you were using this partial in your custom Blade views, you should update your code to use the component instead.

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

**After:**
```blade
<ui-docs-callout :topic="__('Blueprints')" url="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.

```antlers
{{ my_string | urlencode }} // [tl! --]
{{ my_string | urlencode_except_slashes }} // [tl! ++]

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

### `logged_in` variable now uses auth guard from Statamic's `users` config
**Affects app with custom auth guards using the `logged_in` variable** 

The `logged_in` variable now uses the authentication guard configured in Statamic's `users` config file, rather than the default Laravel guard.

```php
// config/auth.php [tl! **]
return [
    'defaults' => [ // [tl! **]
        // v5 used this 👇 [tl! -- **]
        'guard' => env('AUTH_GUARD', 'web'), // [tl! **]
        'passwords' => env('AUTH_PASSWORD_BROKER', 'users'),
    ],
]

// config/statamic/users.php [tl! **]
return [
    'guards' => [  // [tl! **]
        'cp' => 'web',
        // v6 uses this 👇 [tl! ++ **]
        'web' => 'web',  // [tl! **]
    ],   
];
```

In the majority of cases, this results in the exact same behavior.


### Full-measure Static caching
**Affects apps that use full-measure static caching and customize the JS behavior**

The `nocache_js_position` config option has been removed.

The `StaticCache::nocacheJs($script)` method now only replaces the nocache script. It doesn't touch the CSRF token script. Use the new `StaticCache::csrfTokenJs($script)` method if you want to customize the CSRF script.

The `statamic:nocache.replaced` JavaScript event will no longer be dispatched when CSRF tokens are updated. They now get their own separate event: `statamic:csrf.replaced`.

```js
document.addEventListener('statamic:nocache.replaced', (event) => {
    console.log('nocache and csrf have both been replaced');  // [tl! --]
    console.log('nocache has been replaced');  // [tl! ++]
});
document.addEventListener('statamic:csrf.replaced', (event) => {  // [tl! ++]
    console.log('csrf has been replaced');  // [tl! ++]
}); // [tl! ++]
```

### Link fieldtype API and GraphQL responses

The `link` fieldtype in API responses would previously just output the url. In v6 they output an array with more data.

GraphQL needs a subselection:

```graphql
data {
  link_field #[tl! --]
  link_field { #[tl! ++]
    url #[tl! ++]
    title #[tl! ++]
  }
}
```

The REST API will now just give you sub-keys:

```json
{
  "data" {
    "link_field": "/the-url"  // [tl!--]
    "link_field": { // [tl!++]
        "url": "/the-url",  // [tl!++]
        "title": "The Title"  // [tl!++]
    },  // [tl!++]
  }
}
```

### Search: Changes to custom searchables

Searchables should now return collections of references (eg. `entry::the-entry-id`) instead of objects.

```php
return Thing::query()->lazy(); // [tl! remove]
return Thing::query()->lazy()->pluck('reference'); // [tl! add]
```

If your searchable allows for it, you may want to consider adding support for query scopes, which we now recommend over filtering.

```php
$query = Thing::query();

$this->applyQueryScope($query);

return $query->pluck('reference');
```

If you support filtering, you may want to split the "with filter" & "without filter" cases into separate return statements.

The `->filter()` method evaluates every item in the collection, which is an unnecessary performance hit when no filter is configured:

```php
$query = Thing::query();

if ($this->hasFilter()) {
	return $query
		->lazy(config('statamic.search.chunk_size'))  
		->filter($this->filter())  
		->values()  
		->map->reference();
}

return $query->pluck('reference');
```

### Search: Changes to custom search drivers

The `insertDocument` method is now public:

```php
protected function insertDocuments(Documents $documents) // [tl! remove]
public function insertDocuments(Documents $documents) // [tl! add]
```

If you were previously overriding the `insertMultiple` method to chunk documents, you don't need to do that anymore (chunking is now handled by the base method).

If you need to manipulate the fields array before it gets sent to your index, you may define a `fields` method:

```php
public function fields(Searchable $searchable)
{
    return array_merge(
        $this->searchables()->fields($searchable),
        [
            '_some_special_field_' => $searchable->id(),
        ]
    );
}
```

### Bard: Strikes now output `<strike>` tags, rather than `<s>`
**Affects apps relying on the `<s>` tag for strikes.**

Strikes in Bard would previously output `<s>` tags. However, as part of a TipTap update, they now output `<strike>` tags.

If you were styling `<s>` tags, you should update your CSS to target the `<strike>` tag instead.

### Super user authorization

Statamic previously granted super users _all_ permissions globally, bypassing any custom policies or authorisation checks in custom application code and third-party packages.

In Statamic 6, super users are only granted permission for Statamic-related functionality. If you were relying on the previous behaviour, you may need to update your authorisation logic or register a `Gate::before()` hook to restore it:

```php
use Illuminate\Support\Facades\Gate;
use Statamic\Facades\User;

Gate::before(function ($user, $ability): ?bool {
    return optional(User::fromUser($user))->isSuper() ? true : null;
});
```

### `->where('status', '...')` no longer supported for querying entries
**Affects apps or addons querying entries with `->where('status', '…')`**

Querying entries by status using `->where('status', '...')` [was deprecated in v5](/upgrade-guide/4-to-5.md#entries-may-now-only-be-queried-by-a-single-status) and will now throw an exception in v6.

You should use the `->whereStatus()` method instead:

```php
Entry::query()
    ->where('collection', 'blog')
    ->where('status', 'published') // [tl! --]
    ->whereStatus('published') // [tl! ++]
    ->get();
```


## Zero impact changes

### URLs for database nocache regions are now MD5-hashed
**Affects apps storing nocache regions in the database.**

To avoid database column length limits, Statamic now stores an MD5 hash of the URL in the `nocache_regions.url` column instead of the plain URL.

After upgrading, any previously cached nocache regions will be treated as uncached and re-inserted into the database using the hashed URL format.

If you’d prefer to hash existing URLs rather than letting them be regenerated, you can do so manually with a migration:

```php
public function up(): void
{
    DB::transaction(function () {
        DB::connection(config('statamic.static_caching.nocache_db_connection'))
            ->table('nocache_regions')
            ->whereLike('url', 'http%')
            ->orderBy('key')
            ->chunk(100, function ($regions) {
                foreach ($regions as $region) {
                    DB::connection(config('statamic.static_caching.nocache_db_connection'))
                        ->table('nocache_regions')
                        ->where('key', $region->key)
                        ->where('url', $region->url)
                        ->update(['url' => md5($region->url)]);
                }
            });
    });
}
```
