diff --git a/docs/en/appendices/5-0-migration-guide.md b/docs/en/appendices/5-0-migration-guide.md
deleted file mode 100644
index 4492d6eec4..0000000000
--- a/docs/en/appendices/5-0-migration-guide.md
+++ /dev/null
@@ -1,434 +0,0 @@
----
-title: "5.0 Migration Guide"
-description: "Upgrade to CakePHP 5.0: migrate from 4.x, handle breaking changes, update code, understand new requirements and deprecation removals."
----
-
-# 5.0 Migration Guide
-
-CakePHP 5.0 contains breaking changes, and is not backwards compatible with 4.x
-releases. Before attempting to upgrade to 5.0, first upgrade to 4.5 and resolve
-all deprecation warnings.
-
-Refer to the [5.0 Upgrade Guide](../appendices/5-0-upgrade-guide) for step by step instructions
-on how to upgrade to 5.0.
-
-## Deprecated Features Removed
-
-All methods, properties and functionality that were emitting deprecation warnings
-as of 4.5 have been removed.
-
-## Breaking Changes
-
-In addition to the removal of deprecated features there have been breaking
-changes made:
-
-### Global
-
-- Type declarations were added to all function parameter and returns where possible. These are intended
- to match the docblock annotations, but include fixes for incorrect annotations.
-
-- Type declarations were added to all class properties where possible. These also include some fixes for
- incorrect annotations.
-
-- The `SECOND`, `MINUTE`, `HOUR`, `DAY`, `WEEK`, `MONTH`, `YEAR` constants were removed.
-
-- Use of `#[\AllowDynamicProperties]` removed everywhere. It was used for the following classes:
- - `Command/Command`
- - `Console/Shell`
- - `Controller/Component`
- - `Controller/Controller`
- - `Mailer/Mailer`
- - `View/Cell`
- - `View/Helper`
- - `View/View`
-
-- The supported database engine versions were updated:
- - MySQL (5.7 or higher)
- - MariaDB (10.1 or higher)
- - PostgreSQL (9.6 or higher)
- - Microsoft SQL Server (2012 or higher)
- - SQLite 3 (3.16 or higher)
-
-### Auth
-
-- `Auth` has been removed. Use the [cakephp/authentication](https://book.cakephp.org/authentication/3/en/index.html) and
- [cakephp/authorization](https://book.cakephp.org/authorization/3/en/index.html) plugins instead.
-
-### Cache
-
-- The `Wincache` engine was removed. The wincache extension is not supported
- on PHP 8.
-
-### Collection
-
-- `combine()` now throws an exception if the key path or group path doesn't exist or contains a null value.
- This matches the behavior of `indexBy()` and `groupBy()`.
-
-### Console
-
-- `BaseCommand::__construct()` was removed.
-- `ConsoleIntegrationTestTrait::useCommandRunner()` was removed since it's no longer needed.
-- `Shell` has been removed and should be replaced with [Command](https://book.cakephp.org/5/en/console-commands/commands.html)
-- `ConsoleOptionParser::addSubcommand()` was removed alongside the removal of
- `Shell`. Subcommands should be replaced with `Command` classes that
- implement `Command::defaultName()` to define the necessary command name.
-- `BaseCommand` now emits `Command.beforeExecute` and
- `Command.afterExecute` events around the command's `execute()` method
- being invoked by the framework.
-
-### Connection
-
-- `Connection::prepare()` has been removed. You can use `Connection::execute()`
- instead to execute a SQL query by specifing the SQL string, params and types in a single call.
-- `Connection::enableQueryLogging()` has been removed. If you haven't enabled logging
- through the connection config then you can later set the logger instance for the
- driver to enable query logging `$connection->getDriver()->setLogger()`.
-
-### Controller
-
-- The method signature for `Controller::__construct()` has changed.
- So you need to adjust your code accordingly if you are overriding the constructor.
-- After loading components are no longer set as dynamic properties. Instead
- `Controller` uses `__get()` to provide property access to components. This
- change can impact applications that use `property_exists()` on components.
-- The components' `Controller.shutdown` event callback has been renamed from
- `shutdown` to `afterFilter` to match the controller one. This makes the callbacks more consistent.
-- `PaginatorComponent` has been removed and should be replaced by calling `$this->paginate()` in your controller or
- using `Cake\Datasource\Paging\NumericPaginator` directly
-- `RequestHandlerComponent` has been removed. See the [4.4 migration](https://book.cakephp.org/4/en/appendices/4-4-migration-guide.html#requesthandlercomponent) guide for how to upgrade
-- `SecurityComponent` has been removed. Use `FormProtectionComponent` for form tampering protection
- or `HttpsEnforcerMiddleware` to enforce use of HTTPS for requests instead.
-- `Controller::paginate()` no longer accepts query options like `contain` for
- its `$settings` argument. You should instead use the `finder` option
- `$this->paginate($this->Articles, ['finder' => 'published'])`. Or you can
- create required select query before hand and then pass it to `paginate()`
- `$query = $this->Articles->find()->where(['is_published' => true]); $this->paginate($query);`.
-
-### Core
-
-- The function `getTypeName()` has been dropped. Use PHP's `get_debug_type()` instead.
-- The dependency on `league/container` was updated to `4.x`. This will
- require the addition of typehints to your `ServiceProvider` implementations.
-- `deprecationWarning()` now has a `$version` parameter.
-- The `App.uploadedFilesAsObjects` configuration option has been removed
- alongside of support for PHP file upload shaped arrays throughout the
- framework.
-- `ClassLoader` has been removed. Use composer to generate autoload files instead.
-
-### Database
-
-- The `DateTimeType` and `DateType` now always return immutable objects.
- Additionally, the interface for `Date` objects reflects the `ChronosDate`
- interface which lacks all the time related methods that were present in
- CakePHP 4.x.
-- `DateType::setLocaleFormat()` no longer accepts an array.
-- `Query` now accepts only `\Closure` parameters instead of `callable`. Callables can be converted
- to closures using the new first-class array syntax in PHP 8.1.
-- `Query::execute()` no longer runs results decorator callbacks. You must use `Query::all()` instead.
-- `TableSchemaAwareInterface` was removed.
-- `Driver::quote()` was removed. Use prepared statements instead.
-- `Query::orderBy()` was added to replace `Query::order()`.
-- `Query::groupBy()` was added to replace `Query::group()`.
-- `SqlDialectTrait` has been removed and all its functionality has been moved
- into the `Driver` class itself.
-- `CaseExpression` has been removed and should be replaced with
- `QueryExpression::case()` or `CaseStatementExpression`
-- `Connection::connect()` has been removed. Use
- `$connection->getDriver()->connect()` instead.
-- `Connection::disconnect()` has been removed. Use
- `$connection->getDriver()->disconnect()` instead.
-- `cake.database.queries` has been added as an alternative to the `queriesLog` scope
-- The ability to enable/disable ResultSet buffering has been removed. Results are always buffered.
-
-### Datasource
-
-- The `getAccessible()` method was added to `EntityInterface`. Non-ORM
- implementations need to implement this method now.
-- The `aliasField()` method was added to `RepositoryInterface`. Non-ORM
- implementations need to implement this method now.
-
-### Event
-
-- Event payloads must be an array. Other object such as `ArrayAccess` are no longer cast to array and will raise a `TypeError` now.
-- It is recommended to adjust event handlers to be void methods and use `$event->setResult()` instead of returning the result
-
-### Error
-
-- `ErrorHandler` and `ConsoleErrorHandler` have been removed. See the [4.4 migration](https://book.cakephp.org/4/en/appendices/4-4-migration-guide.html#errorhandler-consoleerrorhandler) guide for how to upgrade
-- `ExceptionRenderer` has been removed and should be replaced with `WebExceptionRenderer`
-- `ErrorLoggerInterface::log()` has been removed and should be replaced with `ErrorLoggerInterface::logException()`
-- `ErrorLoggerInterface::logMessage()` has been removed and should be replaced with `ErrorLoggerInterface::logError()`
-
-### Filesystem
-
-- The Filesystem package was removed, and `Filesystem` class was moved to the Utility package.
-
-### Http
-
-- `ServerRequest` is no longer compatible with `files` as arrays. This
- behavior has been disabled by default since 4.1.0. The `files` data will now
- always contain `UploadedFileInterfaces` objects.
-
-### I18n
-
-- `FrozenDate` was renamed to `Date` and `FrozenTime` was renamed to `DateTime`.
-- `Time` now extends `Cake\Chronos\ChronosTime` and is therefore immutable.
-- `Date` objects do not extend `DateTimeInterface` anymore - therefore you can't compare them with `DateTime` objects.
- See the [cakephp/chronos release documentation](https://github.com/cakephp/chronos/releases/tag/3.0.2) for more information.
-- `Date::parseDateTime()` was removed.
-- `Date::parseTime()` was removed.
-- `Date::setToStringFormat()` and `Date::setJsonEncodeFormat()` no longer accept an array.
-- `Date::i18nFormat()` and `Date::nice()` no longer accept a timezone parameter.
-- Translation files for plugins with vendor prefixed names (`FooBar/Awesome`) will now have that
- prefix in the file name, e.g. `foo_bar_awesome.po` to avoid collision with a `awesome.po` file
- from a corresponding plugin (`Awesome`).
-
-### Log
-
-- Log engine config now uses `null` instead of `false` to disable scopes.
- So instead of `'scopes' => false` you need to use `'scopes' => null` in your log config.
-
-### Mailer
-
-- `Email` has been removed. Use [Mailer](https://book.cakephp.org/5/en/core-libraries/email.html) instead.
-- `cake.mailer` has been added as an alternative to the `email` scope
-
-### ORM
-
-- `EntityTrait::has()` now returns `true` when an attribute exists and is
- set to `null`. In previous versions of CakePHP this would return `false`.
- See the release notes for 4.5.0 for how to adopt this behavior in 4.x.
-- `EntityTrait::extractOriginal()` now returns only existing fields, similar to `extractOriginalChanged()`.
-- Finder arguments are now required to be associative arrays as they were always expected to be.
-- `TranslateBehavior` now defaults to the `ShadowTable` strategy. If you are
- using the `Eav` strategy you will need to update your behavior configuration
- to retain the previous behavior.
-- `allowMultipleNulls` option for `isUnique` rule now default to true matching
- the original 3.x behavior.
-- `Table::query()` has been removed in favor of query-type specific functions.
-- `Table::updateQuery()`, `Table::selectQuery()`, `Table::insertQuery()`, and
- `Table::deleteQuery()`) were added and return the new type-specific query objects below.
-- `SelectQuery`, `InsertQuery`, `UpdateQuery` and `DeleteQuery` were added
- which represent only a single type of query and do not allow switching between query types nor
- calling functions unrelated to the specific query type.
-- `Table::_initializeSchema()` has been removed and should be replaced by calling
- `$this->getSchema()` inside the `initialize()` method.
-- `SaveOptionsBuilder` has been removed. Use a normal array for options instead.
-
-### Known Issues
-
-**Memory usage with large result sets**
-
-Compared to CakePHP 4.x, when working with large data sets (especially when
-calling collection methods like `extract()` on the result set), you may encounter
-high memory usage due to the entire result set being buffered in memory.
-
-You can work around this issue by disabling results buffering for the query:
-
-```php
-$results = $articles->find()
- ->disableBufferedResults()
- ->all();
-```
-
-Depending on your use case, you may also consider using disabling hydration:
-
-```php
-$results = $articles->find()
- ->disableHydration()
- ->all();
-```
-
-The above will disable creation of entity objects and return rows as arrays instead.
-
-### Routing
-
-- Static methods `connect()`, `prefix()`, `scope()` and `plugin()` of the `Router` have been removed and
- should be replaced by calling their non-static method variants via the `RouteBuilder` instance.
-- `RedirectException` has been removed. Use `\Cake\Http\Exception\RedirectException` instead.
-
-### TestSuite
-
-- `TestSuite` was removed. Users should use environment variables to customize
- unit test settings instead.
-- `TestListenerTrait` was removed. PHPUnit dropped support for these listeners.
- See [PHPUnit Upgrade](../appendices/phpunit-upgrade)
-- `IntegrationTestTrait::configRequest()` now merges config when called multiple times
- instead of replacing the currently present config.
-
-### Validation
-
-- `Validation::isEmpty()` is no longer compatible with file upload shaped
- arrays. Support for PHP file upload arrays has been removed from
- `ServerRequest` as well so you should not see this as a problem outside of
- tests.
-- Previously, most data validation error messages were simply `The provided value is invalid`.
- Now, the data validation error messages are worded more precisely.
- For example, ``The provided value must be greater than or equal to `5`.``
-
-### View
-
-- `ViewBuilder` options are now truly associative (string keys).
-- `NumberHelper` and `TextHelper` no longer accept an `engine` config.
-- `ViewBuilder::setHelpers()` parameter `$merge` was removed. Use `ViewBuilder::addHelpers()` instead.
-- Inside `View::initialize()`, prefer using `addHelper()` instead of `loadHelper()`.
- All configured helpers will be loaded afterwards, anyway.
-- `View\Widget\FileWidget` is no longer compatible with PHP file upload shaped
- arrays. This is aligned with `ServerRequest` and `Validation` changes.
-- `FormHelper` no longer sets `autocomplete=off` on CSRF token fields. This
- was a workaround for a Safari bug that is no longer relevant.
-
-## Deprecations
-
-The following is a list of deprecated methods, properties and behaviors. These
-features will continue to function in 5.x and will be removed in 6.0.
-
-### Database
-
-- `Query::order()` was deprecated. Use `Query::orderBy()` instead now that
- `Connection` methods are no longer proxied. This aligns the function name
- with the SQL statement.
-- `Query::group()` was deprecated. Use `Query::groupBy()` instead now that
- `Connection` methods are no longer proxied. This aligns the function name
- with the SQL statement.
-
-### ORM
-
-- Calling `Table::find()` with options array is deprecated. Use [named arguments](https://www.php.net/manual/en/functions.arguments.php#functions.named-arguments)
- instead. For e.g. instead of `find('all', ['conditions' => $array])` use
- `find('all', conditions: $array)`. Similarly for custom finder options, instead
- of `find('list', ['valueField' => 'name'])` use `find('list', valueField: 'name')`
- or multiple named arguments like `find(type: 'list', valueField: 'name', conditions: $array)`.
-
-## New Features
-
-### Improved type checking
-
-CakePHP 5 leverages the expanded type system feature available in PHP 8.1+.
-CakePHP also uses `assert()` to provide improved error messages and additional
-type soundness. In production mode, you can configure PHP to not generate
-code for `assert()` yielding improved application performance. See the
-[Symlink Assets](../deployment#symlink-assets) for how to do this.
-
-### Collection
-
-- Added `unique()` which filters out duplicate value specified by provided callback.
-- `reject()` now supports a default callback which filters out truthy values which is
- the inverse of the default behavior of `filter()`
-
-### Core
-
-- The `services()` method was added to `PluginInterface`.
-- `PluginCollection::addFromConfig()` has been added to [simplify plugin loading](../plugins#loading-a-plugin).
-
-### Database
-
-- `ConnectionManager` now supports read and write connection roles. Roles can be configured
- with `read` and `write` keys in the connection config that override the shared config.
-- `Query::all()` was added which runs result decorator callbacks and returns a result set for select queries.
-- `Query::comment()` was added to add a SQL comment to the executed query. This makes it easier to debug queries.
-- `EnumType` was added to allow mapping between PHP backed enums and a string or integer column.
-- `getMaxAliasLength()` and `getConnectionRetries()` were added
- to `DriverInterface`.
-- Supported drivers now automatically add auto-increment only to integer primary keys named "id" instead
- of all integer primary keys. Setting 'autoIncrement' to false always disables on all supported drivers.
-
-### Http
-
-- Added support for [PSR-17](https://www.php-fig.org/psr/psr-17/) factories
- interface. This allows `cakephp/http` to provide a client implementation to
- libraries that allow automatic interface resolution like php-http.
-- Added `CookieCollection::__get()` and `CookieCollection::__isset()` to add
- ergonomic ways to access cookies without exceptions.
-
-### ORM
-
-### Required Entity Fields
-
-Entities have a new opt-in functionality that allows making entities handle
-properties more strictly. The new behavior is called 'required fields'. When
-enabled, accessing properties that are not defined in the entity will raise
-exceptions. This impacts the following usage:
-
-```php
-$entity->get();
-$entity->has();
-$entity->getOriginal();
-isset($entity->attribute);
-$entity->attribute;
-```
-
-Fields are considered defined if they pass `array_key_exists`. This includes
-null values. Because this can be a tedious to enable feature, it was deferred to
-5.0. We'd like any feedback you have on this feature as we're considering making
-this the default behavior in the future.
-
-### Typed Finder Parameters
-
-Table finders can now have typed arguments as required instead of an options array.
-For e.g. a finder for fetching posts by category or user:
-
-```php
-public function findByCategoryOrUser(SelectQuery $query, array $options): SelectQuery
-{
- if (isset($options['categoryId'])) {
- $query->where(['category_id' => $options['categoryId']]);
- }
- if (isset($options['userId'])) {
- $query->where(['user_id' => $options['userId']]);
- }
-
- return $query;
-}
-```
-
-can now be written as:
-
-```php
-public function findByCategoryOrUser(SelectQuery $query, ?int $categoryId = null, ?int $userId = null): SelectQuery
-{
- if ($categoryId) {
- $query->where(['category_id' => $categoryId]);
- }
- if ($userId) {
- $query->where(['user_id' => $userId]);
- }
-
- return $query;
-}
-```
-
-The finder can then be called as `find('byCategoryOrUser', userId: $somevar)`.
-You can even include the special named arguments for setting query clauses.
-`find('byCategoryOrUser', userId: $somevar, conditions: ['enabled' => true])`.
-
-A similar change has been applied to the `RepositoryInterface::get()` method:
-
-```php
-public function view(int $id)
-{
- $author = $this->Authors->get($id, [
- 'contain' => ['Books'],
- 'finder' => 'latest',
- ]);
-}
-```
-
-can now be written as:
-
-```php
-public function view(int $id)
-{
- $author = $this->Authors->get($id, contain: ['Books'], finder: 'latest');
-}
-```
-
-### TestSuite
-
-- `IntegrationTestTrait::requestAsJson()` has been added to set JSON headers for the next request.
-
-### Plugin Installer
-
-- The plugin installer has been updated to automatically handle class autoloading
- for your app plugins. So you can remove the namespace to path mappings for your
- plugins from your `composer.json` and just run `composer dumpautoload`.
diff --git a/docs/en/appendices/5-0-upgrade-guide.md b/docs/en/appendices/5-0-upgrade-guide.md
deleted file mode 100644
index 7c458f713b..0000000000
--- a/docs/en/appendices/5-0-upgrade-guide.md
+++ /dev/null
@@ -1,75 +0,0 @@
----
-title: "5.0 Upgrade Guide"
-description: "Upgrade to CakePHP 5.0 from 4.x. Fix deprecations, update to PHP 8.1+, run rector tool, and update dependencies following this step-by-step guide."
----
-
-# 5.0 Upgrade Guide
-
-First, check that your application is running on latest CakePHP 4.x version.
-
-## Fix Deprecation Warnings
-
-Once your application is running on latest CakePHP 4.x, enable deprecation warnings in **config/app.php**:
-
-```php
-'Error' => [
- 'errorLevel' => E_ALL,
-],
-```
-
-Now that you can see all the warnings, make sure these are fixed before proceeding with the upgrade.
-
-Some potentially impactful deprecations you should make sure you have addressed
-are:
-
-- `Table::query()` was deprecated in 4.5.0. Use `selectQuery()`,
- `updateQuery()`, `insertQuery()` and `deleteQuery()` instead.
-
-## Upgrade to PHP 8.1
-
-If you are not running on **PHP 8.1 or higher**, you will need to upgrade PHP before updating CakePHP.
-
-> [!NOTE]
-> CakePHP 5.0 requires **a minimum of PHP 8.1**.
-
-
-
-## Use the Upgrade Tool
-
-> [!NOTE]
-> The upgrade tool only works on applications running on latest CakePHP 4.x. You cannot run the upgrade tool after updating to CakePHP 5.0.
-
-Because CakePHP 5 leverages union types and `mixed`, there are many
-backwards incompatible changes concerning method signatures and file renames.
-To help expedite fixing these tedious changes there is an upgrade CLI tool:
-
-```bash
-# Install the upgrade tool
-git clone https://github.com/cakephp/upgrade
-cd upgrade
-git checkout 5.x
-composer install --no-dev
-```
-
-With the upgrade tool installed you can now run it on your application or
-plugin:
-
-```bash
-bin/cake upgrade rector --rules cakephp50
-bin/cake upgrade rector --rules chronos3
-```
-
-## Update CakePHP Dependency
-
-After applying rector refactorings you need to upgrade CakePHP, its plugins, PHPUnit
-and maybe other dependencies in your `composer.json`.
-This process heavily depends on your application so we recommend you compare your
-`composer.json` with what is present in [cakephp/app](https://github.com/cakephp/app/blob/5.x/composer.json).
-
-After the version strings are adjusted in your `composer.json` execute
-`composer update -W` and check its output.
-
-## Update app files based upon latest app template
-
-Next, ensure the rest of your application has been updated to be based upon the
-latest version of [cakephp/app](https://github.com/cakephp/app/blob/5.x/).
diff --git a/docs/en/appendices/5-1-migration-guide.md b/docs/en/appendices/5-1-migration-guide.md
deleted file mode 100644
index dadebc3e70..0000000000
--- a/docs/en/appendices/5-1-migration-guide.md
+++ /dev/null
@@ -1,184 +0,0 @@
----
-title: "5.1 Migration Guide"
-description: "Migrate to CakePHP 5.1: explore new features, deprecations, improvements, and upgrade your 5.0 application with this comprehensive guide."
----
-
-# 5.1 Migration Guide
-
-The 5.1.0 release is backwards compatible with 5.0. It adds new functionality
-and introduces new deprecations. Any functionality deprecated in 5.x will be
-removed in 6.0.0.
-
-## Upgrade Tool
-
-The [upgrade tool](../appendices/migration-guides) provides rector rules for
-automating some of the migration work. Run rector before updating your
-`composer.json` dependencies:
-
-```bash
-bin/cake upgrade rector --rules cakephp51
-```
-
-## Behavior Changes
-
-- Connection now creates unique read and write drivers if the keys `read` or
- `write` are present in the config regardless of values.
-- FormHelper no longer generates `aria-required` attributes on input elements
- that also have the `required` attribute set. The `aria-required` attribute
- is redundant on these elements and generates HTML validation warnings. If you
- are using `aria-required` attribute in styling or scripting you'll need to
- update your application.
-- Adding associations with duplicate names will now raise exceptions. You can
- use `$table->associations()->has()` to conditionally define associations if
- required.
-- Text Utility and TextHelper methods around truncation and maximum length are using
- a UTF-8 character for `ellipsis` instead of `...` legacy characters.
-- `TableSchema::setColumnType()` now throws an exception if the specified column
- does not exist.
-- `PluginCollection::addPlugin()` now throws an exception if a plugin of the same
- name is already added.
-- `TestCase::loadPlugins()` will now clear out any previously loaded plugins. So
- you must specify all plugins required for any subsequent tests.
-- The hashing algorithm for `Cache` configurations that use `groups`. Any
- keys will have new group prefix hashes generated which will cause cache
- misses. Consider an incremental deploy to avoid operating on an entirely cold
- cache.
-- `FormHelper::getFormProtector()` now returns `null` in addition to its
- previous types. This allows dynamic view code to run with fewer errors and
- shouldn't impact most applications.
-- The default value for `valueSeparator` in `Table::findList()` is now
- a single space instead of `;`.
-- `ErrorLogger` uses `Psr\Log\LogTrait` now.
-- `Database\QueryCompiler::$_orderedUnion` was removed.
-
-## Deprecations
-
-### I18n
-
-- The `_cake_core_` cache config key has been renamed to `_cake_translations_`.
-
-### Mailer
-
-- `Mailer::setMessage()` is deprecated. It has unintuitive behavior and very
- low usage.
-
-## New Features
-
-### Cache
-
-- `RedisEngine` now supports a `tls` option that enables connecting to redis
- over a TLS connection. You can use the `ssl_ca`, `ssl_cert` and
- `ssl_key` options to define the TLS context for redis.
-
-### Command
-
-- `bin/cake plugin list` has been added to list all available plugins,
- their load configuration and version.
-- Optional `Command` arguments can now have a `default` value.
-- `BannerHelper` was added. This command helper can format text as a banner
- with a coloured background and padding.
-- Additional default styles for `info.bg`, `warning.bg`, `error.bg` and
- `success.bg` were added to `ConsoleOutput`.
-
-### Console
-
-- `Arguments::getBooleanOption()` and `Arguments::getMultipleOption()` were added.
-- `Arguments::getArgument()` will now raise an exception if an unknown
- argument name is provided. This helps prevent mixing up option/argument names.
-
-### Controller
-
-- Components can now use the DI container to have dependencies resolved and
- provided as constructor parameters just like Controllers and Commands do.
-
-### Core
-
-- `PluginConfig` was added. Use this class to get all available plugins, their load config and versions.
-- The `toString`, `toInt`, `toBool` functions were added. They give you
- a typesafe way to cast request data or other input and return `null` when conversion fails.
-- `pathCombine()` was added to help build paths without worrying about duplicate and trailing slashes.
-- A new `events` hook was added to the `BaseApplication` as well as the `BasePlugin` class. This hook
- is the recommended way to register global event listeners for you application. See [Registering Listeners](../core-libraries/events#registering-event-listeners)
-
-### Database
-
-- Support for `point`, `linestring`, `polygon` and `geometry` types were
- added. These types are useful when working with geospatial or cartesian
- co-ordinates. Sqlite support uses text columns under the hood and lacks
- functions to manipulate data as geospatial values.
-- `SelectQuery::__debugInfo()` now includes which connection role the query
- is for.
-- `SelectQuery::intersect()` and `SelectQuery::intersectAll()` were added.
- These methods enable queries using `INTERSECT` and `INTERSECT ALL`
- conjunctions to be expressed.
-- New supports features were added for `intersect`, `intersect-all` and
- `set-operations-order-by` features.
-- The ability to fetch records without buffering which existed in 4.x has been restored.
- Methods `SelectQuery::enableBufferedResults()`, `SelectQuery::disableBufferedResults()`
- and `SelectQuery::isBufferedResultsEnabled()` have been re-added.
-
-### Datasource
-
-- `RulesChecker::remove()`, `removeCreate()`, `removeUpdate()`, and
- `removeDelete()` methods were added. These methods allow you to remove rules
- by name.
-
-### Http
-
-- `SecurityHeadersMiddleware::setPermissionsPolicy()` was added. This method
- adds the ability to define `permissions-policy` header values.
-- `Client` now emits `HttpClient.beforeSend` and `HttpClient.afterSend`
- events when requests are sent. You can use these events to perform logging,
- caching or collect telemetry.
-- `Http\Server::terminate()` was added. This method triggers the
- `Server.terminate` event which can be used to run logic after the response
- has been sent in fastcgi environments. In other environments the
- `Server.terminate` event runs *before* the response has been sent.
-
-### I18n
-
-- `Number::formatter()` and `currency()` now accept a `roundingMode`
- option to override how rounding is done.
-- The `toDate`, and `toDateTime` functions were added. They give you
- a typesafe way to cast request data or other input and return `null` when
- conversion fails.
-
-### ORM
-
-- Setting the `preserveKeys` option on association finder queries. This can be
- used with `formatResults()` to replace association finder results with an
- associative array.
-- SQLite columns with names containing `json` can now be mapped to `JsonType`.
- This is currently an opt-in feature which is enabled by setting the `ORM.mapJsonTypeForSqlite`
- configure value to `true` in your app.
-
-### TestSuite
-
-- CakePHP as well as the app template have been updated to use PHPUnit `^10.5.5 || ^11.1.3"`. - `ConnectionHelper` methods are now all static. This class has no state and its methods were updated to be static. - `LogTestTrait` was added. This new trait makes it easy to capture logs in your tests and make assertions on the presence or absence of log messages. - `IntegrationTestTrait::replaceRequest()` was added.
-
-### Utility
-
-- `Hash::insert()` and `Hash::remove()` now accept `ArrayAccess` objects along with `array` data.
-
-### Validation
-
-- `Validation::enum()` and `Validator::enum()` were added. These validation
- methods simplify validating backed enum values.
-- `Validation::enumOnly()` and `Validation::enumExcept()` were added to check for specific cases
- and further simplify validating backed enum values.
-
-### View
-
-- View cells now emit events around their actions `Cell.beforeAction` and
- `Cell.afterAction`.
-- `NumberHelper::format()` now accepts a `roundingMode` option to override how
- rounding is done.
-
-### Helpers
-
-- `TextHelper::autoLinkUrls()` has options added for better link label printing:
- - `stripProtocol`: Strips `http://` and `https://` from the beginning of the link. Default off.
- - `maxLength`: The maximum length of the link label. Default off.
- - `ellipsis`: The string to append to the end of the link label. Defaults to UTF8 version.
-- `HtmlHelper::meta()` can now create a meta tag containing the current CSRF
- token using `meta('csrfToken')`.
diff --git a/docs/en/appendices/5-2-migration-guide.md b/docs/en/appendices/5-2-migration-guide.md
deleted file mode 100644
index 277ac03aa5..0000000000
--- a/docs/en/appendices/5-2-migration-guide.md
+++ /dev/null
@@ -1,134 +0,0 @@
----
-title: "5.2 Migration Guide"
-description: "Migrate to CakePHP 5.2: understand new features, deprecations, breaking changes, and upgrade your application from 5.0/5.1 smoothly."
----
-
-# 5.2 Migration Guide
-
-The 5.2.0 release is backwards compatible with 5.0. It adds new functionality
-and introduces new deprecations. Any functionality deprecated in 5.x will be
-removed in 6.0.0.
-
-## Upgrade Tool
-
-The [upgrade tool](../appendices/migration-guides) provides rector rules for
-automating some of the migration work. Run rector before updating your
-`composer.json` dependencies:
-
-```bash
-bin/cake upgrade rector --rules cakephp52
-```
-
-## Behavior Changes
-
-- `ValidationSet::add()` will now raise errors when a rule is added with
- a name that is already defined. This change aims to prevent rules from being
- overwritten by accident.
-- `Http\Session` will now raise an exception when an invalid session preset is
- used.
-- `FormProtectionComponent` now raises `Cake\Controller\Exception\FormProtectionException`. This
- class is a subclass of `BadRequestException`, and offers the benefit of
- being filterable from logging.
-- `NumericPaginator::paginate()` now uses the `finder` option even when a `SelectQuery` instance is passed to it.
-
-## Deprecations
-
-### Console
-
-- `Arguments::getMultipleOption()` is deprecated. Use `getArrayOption()`
- instead.
-
-### Datasource
-
-- The ability to cast an `EntityInterface` instance to string has been deprecated.
- You should `json_encode()` the entity instead.
-- Mass assigning multiple entity fields using `EntityInterface::set()` is deprecated.
- Use `EntityInterface::patch()` instead. For e.g. change usage like
- `$entity->set(['field1' => 'value1', 'field2' => 'value2'])` to
- `$entity->patch(['field1' => 'value1', 'field2' => 'value2'])`.
-
-### Event
-
-- Returning values from event listeners / callbacks is deprecated. Use `$event->setResult()`
- instead or `$event->stopPropagation()` to just stop the event propagation.
-
-### View
-
-- The `errorClass` option of `FormHelper` has been deprecated in favour of
- using a template string. To upgrade move your `errorClass` definition to
- a template set. See [Customizing Templates](../views/helpers/form#customizing-templates).
-
-## New Features
-
-### Console
-
-- The `cake counter_cache` command was added. This command can be used to
- regenerate counters for models that use `CounterCacheBehavior`.
-- `ConsoleIntegrationTestTrait::debugOutput()` makes it easier to debug
- integration tests for console commands.
-- `ConsoleInputArgument` now supports a `separator` option. This option
- allows positional arguments to be delimited with a character sequence like
- `,`. CakePHP will split the positional argument into an array when arguments
- are parsed.
-- `Arguments::getArrayArgumentAt()`, and `Arguments::getArrayArgument()`
- were added. These methods allow you to read `separator` delimitered
- positional arguments as arrays.
-- `ConsoleInputOption` now supports a `separator` option. This option
- allows option values to be delimited with a character sequence like
- `,`. CakePHP will split the option value into an array when arguments
- are parsed.
-- `Arguments::getArrayArgumentAt()`, `Arguments::getArrayArgument()`, and
- `Arguments::getArrayOption()`
- were added. These methods allow you to read `separator` delimitered
- positional arguments as arrays.
-
-### Database
-
-- The `nativeuuid` type was added. This type enables `uuid` columns to be
- used in Mysql connections with MariaDB. In all other drivers, `nativeuuid`
- is an alias for `uuid`.
-- `Cake\Database\Type\JsonType::setDecodingOptions()` was added. This method
- lets you define the value for the `$flags` argument of `json_decode()`.
-- `CounterCacheBehavior::updateCounterCache()` was added. This method allows
- you to update the counter cache values for all records of the configured
- associations. `CounterCacheCommand` was also added to do the same through the
- console.
-- `Cake\Database\Driver::quote()` was added. This method provides a way to
- quote values to be used in SQL queries where prepared statements cannot be
- used.
-
-### Datasource
-
-- Application rules can now use `Closure` to define the validation message.
- This allows you to create dynamic validation messages based on the entity
- state and validation rule options.
-
-### Error
-
-- Custom exceptions can have specific error handling logic defined in
- `ErrorController`.
-
-### ORM
-
-- `CounterCacheBehavior::updateCounterCache()` has been added. This method
- allows you to update the counter cache values for all records of the configured
- associations.
-- `BelongsToMany::setJunctionProperty()` and `getJunctionProperty()` were
- added. These methods allow you to customize the `_joinData` property that is
- used to hydrate junction table records.
-- `Table::findOrCreate()` now accepts an array as second argument to directly pass data in.
-
-### TestSuite
-
-- `TestFixture::$strictFields` was added. Enabling this property will make
- fixtures raise an error if a fixture's record list contains fields that do not
- exist in the schema.
-
-### View
-
-- `FormHelper::deleteLink()` has been added as convenience wrapper for delete links in
- templates using `DELETE` method.
-- `HtmlHelper::importmap()` was added. This method allows you to define
- import maps for your JavaScript files.
-- `FormHelper` now uses the `containerClass` template to apply a class to
- the form control div. The default value is `input`.
diff --git a/docs/en/appendices/5-3-migration-guide.md b/docs/en/appendices/5-3-migration-guide.md
deleted file mode 100644
index ba29464945..0000000000
--- a/docs/en/appendices/5-3-migration-guide.md
+++ /dev/null
@@ -1,266 +0,0 @@
----
-title: "5.3 Migration Guide"
-description: "Upgrade to CakePHP 5.3: discover new features, deprecations, improvements, and migrate from 5.0-5.2 with this detailed guide."
----
-
-# 5.3 Migration Guide
-
-The 5.3.0 release is backwards compatible with 5.0. It adds new functionality
-and introduces new deprecations. Any functionality deprecated in 5.x will be
-removed in 6.0.0.
-
-## Upgrade Tool
-
-The [upgrade tool](../appendices/migration-guides) provides rector rules for
-automating some of the migration work. Run rector before updating your
-`composer.json` dependencies:
-
-```bash
-bin/cake upgrade rector --rules cakephp53
-```
-
-## Upgrade to PHP 8.2
-
-If you are not running on **PHP 8.2 or higher**, you will need to upgrade PHP before updating CakePHP.
-
-> [!NOTE]
-> CakePHP 5.3 requires **a minimum of PHP 8.2**.
-
-## Behavior Changes
-
-### Core
-
-- `InstanceConfigTrait::deleteConfig()` was added. For classes using this trait,
- you can now use `$this->deleteConfig('key')` instead of `$this->setConfig('key', null)`
-
-### Database
-
-- `Query::with()` now accepts an array of expressions to align with other query clauses.
- This also allows clearing the expressions with an empty array.
-
-### ORM
-
-- `joinWith()` now asserts when the association conflicts with an existing join and will overwrite it.
- Because existing code might harmlessly ignore the join or accidentally rely on that behavior, this change is not breaking
- in production for CakePHP 5.
-
-### Validation
-
-- The signature of `Validator::validate(array $data, bool $newRecord = true, array $context = [])` now has an additional third parameter `$context`.
- It can be used to pass necessary context into the validation when marshalling.
-
-### View
-
-- The `format()` and `currency()` methods of `NumberHelper` now accept also null as input and can return any default string here.
- This allows for easier templates, in particular baked ones. Make sure to adjust any extending helper (plugin or app level) by adding that type.
-
-## Deprecations
-
-### Database
-
-- `Query::newExpr()` is deprecated. Use `Query::expr()` instead.
-
-### Form
-
-- `Form::_execute()` is deprecated. You should rename your `_execute`
- methods to `process()` which accepts the same parameters and has the same
- return type.
-
-### Http
-
-- Using `$request->getParam('?')` to get the query params is deprecated.
- Use `$request->getQueryParams()` instead.
-
-### ORM
-
-- Calling behavior methods on table instances is now deprecated. To call
- a method of an attached behavior you need to use
- `$table->getBehavior('Sluggable')->slugify()` instead of `$table->slugify()`.
-- `EntityTrait::isEmpty()` is deprecated. Use `hasValue()` instead.
-
-### Plugin
-
-- Loading of plugins without a plugin class is deprecated. For your existing plugins
- which don't have one, you can use the `bin/cake bake plugin MyPlugin --class-only`
- command, which will create the file `plugins/MyPlugin/src/MyPlugin.php`.
-
-### View
-
-- Passing an array as the first argument to `BreadcrumbsHelper::add()` and
- `BreadcrumbsHelper::prepend()` is deprecated. Use `addMany()` and
- `prependMany()` instead.
-
-## New Features
-
-### Cache
-
-- Added Redis Cluster support to `RedisEngine`. Configure the `cluster` option
- with an array of server addresses to enable cluster mode.
-- Several [Cache Events](../core-libraries/caching#cache-events) were added to allow monitoring the caching behavior.
-
-### Collection
-
-- `Collection::any()` was added to replace `Collection::some()` with a more familiar name.
-
-### Command
-
-- `cake plugin assets symlink` command now supports a `--relative` option to
- create relative path symlinks. This is useful when creating symlinks within
- containers that use volume mounts.
-- `cake server` now supports a `--frankenphp` option that will start the
- development server with [FrankenPHP](https://frankenphp.dev/).
-
-### Console
-
-- Added `TreeHelper` which outputs an array as a tree such as an array of filesystem
- directories as array keys and files as lists under each directory.
-- Commands can now implement `getGroup()` to customize how commands are
- grouped in `bin/cake -h` output.
-- `CommandCollection::replace()` was added. This method allows you to replace
- an existing command in the collection without needing to remove and re-add it.
- This is particularly useful when using `autoDiscover` and you want to replace
- a command with a customized version.
-
-### Core
-
-- Added `Configure` attribute to support injecting `Configure` values into
- constructor arguments. See [Configure Dependency Injection](../development/dependency-injection#configure-dependency-injection).
-
-### Database
-
-- Added support for Entra authentication to SqlServer driver.
-- Added `Query::optimizerHint()` which accepts engine-specific optimizer hints.
-- Added `Query::getDriver()` helper which returns the `Driver` for the current connection
- role by default.
-- Added support for `year` column types in MySQL.
-- Added support for `inet`, `cidr` and `macaddr` network column types to
- postgres driver.
-- Added `TypeFactory::getMapped()` to retrieve the mapped class name for a specific type.
- This provides a cleaner API compared to using `TypeFactory::getMap()` with a type argument.
-
-### Error
-
-- `Debugger` now replaces `ROOT` with the
- `Debugger.editorBasePath` Configure value if defined. This improves
- debugging workflows within containerized environments.
-
-### Http
-
-- The new `RateLimitMiddleware` provides configurable rate limiting for your
- application to protect against abuse and ensure fair usage of resources. It
- supports multiple identification strategies (IP, user, route, API key),
- different rate limiting algorithms (sliding window, fixed window, token bucket),
- and advanced features like custom identifiers, request costs, and dynamic limits.
-- `UnprocessableContentException` was added.
-
-### I18n
-
-- Added `DateTimePeriod` which wraps a php `DatePeriod` and returns `DateTime`
- instances when iterating.
-- Added `DatePeriod` which wraps a php `DatePeriod` and returns `Date` instances
- when iterating.
-- Added `toQuarterRange()` method to `DateTime` and `FrozenTime` classes which returns
- an array containing the start and end dates of the quarter for the given date.
-- Added `Date::getTimestamp()`. This method returns an int of the date's
- timestamp.
-
-### Mailer
-
-- Added `Message::addAttachment()` for adding attachments to a message. Like
- other message methods, it can be accessed via the `Mailer` instance as `$mailer->addAttachment()`.
-
-### ORM
-
-- `Table::patchEntity()`, `Table::newEntity()`, `Marshaller::one()` and
- `Marshaller::many()` now accept a `strictFields` option that only applies
- validation to the fields listed in the `fields` option.
-- Added `TableContainer` that you can register in your `Application::services()` to
- add dependency injection for your Tables.
-- Added `SelectQuery::projectAs()` for projecting query results into Data
- Transfer Objects (DTOs) instead of Entity objects. DTOs provide a
- memory-efficient alternative (approximately 3x less memory than entities) for
- read-only data access. See [Dto Projection](../orm/query-builder#dto-projection).
-- Added the `#[CollectionOf]` attribute for declaring the element type of
- array properties in DTOs. This enables proper hydration of nested
- associations into DTOs.
-
-### Pagination
-
-- Added `SortableFieldsBuilder` class enabling fluent configuration of
- sortable fields with advanced features. The `sortableFields` option now
- accepts a callable that receives a `SortableFieldsBuilder` instance,
- allowing you to map friendly sort keys to database fields with multi-column
- sorting and direction control.
-- Added `SortField` class for defining sort field configurations with
- customizable default directions and locked directions (e.g.,
- `SortField::asc('price')` or `SortField::desc('created', locked: true)`).
-- Added support for combined sorting keys in URLs (e.g., `?sort=title-asc` or
- `?sort=price-desc`) in addition to the traditional `?sort=field&direction=asc`
- format.
-
-### Routing
-
-- Added `RouteBuilder::setOptions()` method to set default route options at
- the scope level. This allows you to apply options like `_host`, `_https`,
- and `_port` to all routes within a scope without repeating them on each
- route. Options set at the scope level are inherited by nested scopes and can
- be overridden on individual routes.
-- `EntityRoute` now handles enum value conversions. This enables you to use
- enum backed properties as route parameters. When an enum backed property is
- used in routing, the enum's `value` or `name` will be used.
-- Added `RedirectTrait`. This trait can be used to create custom redirect route
- classes.
-
-### TestSuite
-
-- `assertRedirectBack()` added to assert a successful redirect has been made to the same previous URL.
-- `assertRedirectBackToReferer()` added to assert a successful redirect has been made to the referer URL.
-- `assertFlashMessageContains()` and `assertFlashMessageContainsAt()` were added. These methods enable
- substring matching of flash message content.
-- `TestFixture::$tableAlias` was added. This property lets you define the
- table alias that will be used to load an `ORM\Table` instance for a fixture.
- This improves compatibility for schemas that do not closely follow naming conventions.
-
-### Utility
-
-- `Text::uuid()` now supports configurable UUID generation. You can set a custom
- UUID generator using `Configure::write('Text.uuidGenerator', $closure)` to
- integrate your own UUID generation strategy or third-party libraries.
-
-### Validation
-
-- `ipOrRange()` validation has been added to check for an IP or a range (subnet).
-- When validating within CakePHP marshalling context, the entity will be passed
- into the `context` argument for use inside custom validation rules. This can
- be useful when patching partially and then needing to get that data from the
- entity instead of the passed data.
-- `existsInNullable()` rule has been added. This rule allows `null` values
- in nullable composite foreign keys, which is semantically correct for optional
- relationships. Use `$rules->existsInNullable(['author_id', 'site_id'], 'SiteAuthors')` instead of `existsIn()` when you want to permit null values
- in foreign keys.
-
-### View
-
-- `HtmlHelper::scriptStart()` and `scriptEnd()` now allow simple
- wrapping script tags (``) around inline JavaScript. This
- enables syntax highlighting in many editors to work. The wrapping script tag
- will be removed and replaced with a script tag generated by the helper.
-- `FormHelper` now supports a new option `nestedCheckboxAndRadio`.
- By default, the helper generates inputs of type checkbox and radio nested
- inside their label. Setting the `nestedCheckboxAndRadio` option to `false`
- will turn off the nesting.
-- `ViewBuilder::setConfigMergeStrategy()` was added to control how view options
- are merged with the View class's default configuration. Available strategies are
- `ViewBuilder::MERGE_DEEP` (recursive merge, default) and `ViewBuilder::MERGE_SHALLOW`
- (simple array merge). This is useful when you want to replace array values in view
- options rather than deep merging them.
-- `ViewBuilder::getConfigMergeStrategy()` was added to retrieve the current merge
- strategy setting.
-- `PaginatorHelper::limitControl()` now automatically respects the
- `maxLimit` configuration from the paginator, filtering out any limit options
- that exceed it. A new `steps` option was added to automatically generate limit
- options in multiples of a specific value (e.g., `['steps' => 10]` generates
- 10, 20, 30... up to maxLimit).
-- `BreadcrumbsHelper::addMany()` and `BreadcrumbsHelper::prependMany()`
- were added. These methods allow adding multiple breadcrumbs at once with support
- for shared options that apply to all crumbs.
diff --git a/docs/en/appendices/5-4-migration-guide.md b/docs/en/appendices/5-4-migration-guide.md
deleted file mode 100644
index 562d3d79ff..0000000000
--- a/docs/en/appendices/5-4-migration-guide.md
+++ /dev/null
@@ -1,32 +0,0 @@
-# 5.4 Migration Guide
-
-The 5.4.0 release is backwards compatible with 5.0. It adds new functionality
-and introduces new deprecations. Any functionality deprecated in 5.x will be
-removed in 6.0.0.
-
-## Upgrade Tool
-
-The [upgrade tool](../appendices/migration-guides) provides rector rules for
-automating some of the migration work. Run rector before updating your
-`composer.json` dependencies:
-
-```text
-bin/cake upgrade rector --rules cakephp54
-```
-
-## Behavior Changes
-
-- WIP
-
-## Deprecations
-
-- WIP
-
-## New Features
-
-### Utility
-
-- New `Cake\Utility\Fs\Finder` class provides a fluent, iterator-based API for
- discovering files and directories with support for pattern matching, depth
- control, and custom filters. The `Cake\Utility\Fs\Path` class offers
- cross-platform utilities for path manipulation.
diff --git a/docs/en/appendices/6-0-migration-guide.md b/docs/en/appendices/6-0-migration-guide.md
index 71ee4e0fe7..68aab2c3d1 100644
--- a/docs/en/appendices/6-0-migration-guide.md
+++ b/docs/en/appendices/6-0-migration-guide.md
@@ -1,7 +1,7 @@
# 6.0 Migration Guide
CakePHP 6.0 contains breaking changes, and is not backwards compatible with 5.x.
-Before attempting to upgrade to 6.0 first upgrade to 5.2+ and resolve all
+Before attempting to upgrade to 6.0 first upgrade to 5.3+ and resolve all
deprecation warnings.
## Behavior Changes
@@ -27,60 +27,47 @@ You can find a full list of adjusted methods in the [cakephp/upgrade tool](https
Some methods have also been renamed to better reflect their purpose. These are:
-- `Cake\Console\ConsoleOutput`
- - `_write()` has been renamed to `writeStream()`
+| Class | Old Method(s) | New Method(s) |
+|---------------------------------------|-----------------------------------------------------|--------------------------------------------------------|
+| `Cake\Console\ConsoleOutput` | `_write()` | `writeStream()` |
+| `Cake\Form\Form` | `_execute()` | `process()` |
+| `Cake\Http\Client` | `_sendRequest()` | `processRequest()` |
+| `Cake\Http\ServerRequest` | `_is()` | `isType()` |
+| `Cake\Http\Client\Adapter\Stream` | `_send()` | `processRequest()` |
+| `Cake\I18n\DateFormatTrait` | `_parseDateTime()` | `processDateTime()` |
+| `Cake\Mailer\Transport\SmtpTransport` | `_connect()`
`_disconnect()` | `connectSmtp()`
`disconnectSmtp()` |
+| `Cake\ORM\Table` | `_saveMany()`
`_deleteMany()` | `doSaveMany()`
`doDeleteMany()` |
+| `Cake\ORM\Behavior\TreeBehavior` | `_moveUp()`
`_moveDown()`
`_removeFromTree()` | `doMoveUp()`
`doMoveDown()`
`doRemoveFromTree()` |
+| `Cake\ORM\Association\HasMany` | `_unlink()` | `doUnlink()` |
+| `Cake\ORM\Query\SelectQuery` | `_decorateResults()`
`_execute()` | `ormDecorateResults()`
`ormExecute()` |
+| `Cake\Utility\Hash` | `_filter()`
`_merge()` | `doFilter()`
`doMerge()` |
+| `Cake\Utility\Text` | `_wordWrap()` | `doWordWrap()` |
+| `Cake\Utility\Xml` | `_fromArray()`
`_toArray()` | `doFromArray()`
`doToArray()` |
+| `Cake\View\View` | `_render()` | `renderFile()` |
+| `Cake\View\Helper\PaginatorHelper` | `_numbers()` | `buildNumbers()` |
-- `Cake\Form\Form`
- - `_execute()` has been renamed to `process()`
+### Renamed Properties
-- `Cake\Http\Client`
- - `_sendRequest()` has been renamed to `processRequest()`
+Properties starting with a `_` have been renamed to **remove the leading underscore**.
+You can find a full list of adjusted properties in the
+[cakephp/upgrade tool](https://github.com/cakephp/upgrade/blob/6.x/config/rector/sets/cakephp60.php).
-- `Cake\Http\ServerRequest`
- - `_is()` has been renamed to `isType()`
+Some properties have also been renamed to better reflect their purpose. These are:
-- `Cake\Http\Client\Adapter\Stream`
- - `_send()` has been renamed to `processRequest()`
+- `Cake\ORM\Entity`
+ - `$_accessible` has been renamed to `patchable`
+- `Cake\View\View`
+ - `$_helpers` has been renamed to `helperRegistry` as `$helpers` already exists to hold the configuration
-- `Cake\I18n\DateFormatTrait`
- - `_parseDateTime()` has been renamed to `processDateTime()`
+### Console
-- `Cake\Mailer\Transport\SmtpTransport`
- - `_connect()` has been renamed to `connectSmtp()`
- - `_disconnect()` has been renamed to `disconnectSmtp()`
+- The `validChoice` method on `ConsoleInputArgument` and `ConsoleInputOption` has been renamed to `validateChoice`.
-- `Cake\ORM\Table`
- - `_saveMany()` has been renamed to `doSaveMany()`
- - `_deleteMany()` has been renamed to `doDeleteMany()`
+### Command
-- `Cake\ORM\Behavior\TreeBehavior`
- - `_moveUp()` has been renamed to `doMoveUp()`
- - `_moveDown()` has been renamed to `doMoveDown()`
- - `_removeFromTree()` has been renamed to `doRemoveFromTree()`
-
-- `Cake\ORM\Association\HasMany`
- - `_unlink()` has been renamed to `doUnlink()`
-
-- `Cake\ORM\Query\SelectQuery`
- - `_decorateResults()` has been renamed to `ormDecorateResults()`
- - `_execute()` has been renamed to `ormExecute()`
-
-- `Cake\Utility\Hash`
- - `_filter()` has been renamed to `doFilter()`
- - `_merge()` has been renamed to `doMerge()`
-
-- `Cake\Utility\Text`
- - `_wordWrap()` has been renamed to `doWordWrap()`
-
-- `Cake\Utility\Xml`
- - `_fromArray()` has been renamed to `doFromArray()`
- - `_toArray()` has been renamed to `doToArray()`
-
-- `Cake\View\View`
- - `_render()` has been renamed to `renderFile()`
-
-- `Cake\View\Helper\PaginatorHelper`
- - `_numbers()` has been renamed to `buildNumbers()`
+- Command args and io are now available as properties instead of them being
+ passed down to the execute method. See the current state of
+ [Commands](../console-commands/commands.md) for examples.
### Event
@@ -112,6 +99,12 @@ Some methods have also been renamed to better reflect their purpose. These are:
- The `accessibleFields` option used in e.g. ORM Queries has been
renamed to `patchableFields`.
+### Router
+
+- `RouteBuilder` has adjusted the signature of `scope()`, `prefix()` and `resources()`
+ so the 2nd and 3rd parameters have been swapped.
+ We recommend using named parameters to prevent confusion and make the code more readable.
+
### Utility
- The default placeholder format for `Text::insert()` has been changed.
diff --git a/docs/en/appendices/6-0-upgrade-guide.md b/docs/en/appendices/6-0-upgrade-guide.md
index 9fba6afd74..1ad1c21ea5 100644
--- a/docs/en/appendices/6-0-upgrade-guide.md
+++ b/docs/en/appendices/6-0-upgrade-guide.md
@@ -6,7 +6,7 @@ First, check that your application is running on latest CakePHP 5.x version.
Once your application is running on latest CakePHP 5.x, enable deprecation warnings in **config/app.php**:
-``` text
+```text
'Error' => [
'errorLevel' => E_ALL,
]
@@ -35,7 +35,7 @@ If you are not running on **PHP 8.4 or higher**, you will need to upgrade PHP be
To help expedite fixing tedious changes there is an upgrade CLI tool:
-``` bash
+```bash
# Install the upgrade tool
git clone https://github.com/cakephp/upgrade
cd upgrade
@@ -46,7 +46,7 @@ composer install --no-dev
With the upgrade tool installed you can now run it on your application or
plugin:
-``` text
+```bash
bin/cake upgrade rector --rules cakephp60
```
diff --git a/docs/en/appendices/migration-guides.md b/docs/en/appendices/migration-guides.md
index 82738cd439..cd33d4b30d 100644
--- a/docs/en/appendices/migration-guides.md
+++ b/docs/en/appendices/migration-guides.md
@@ -21,11 +21,11 @@ To use the upgrade tool:
# Install the upgrade tool
git clone https://github.com/cakephp/upgrade
cd upgrade
-git checkout 5.x
+git checkout 6.x
composer install --no-dev
# Run rector with the desired ruleset
-bin/cake upgrade rector --rules cakephp51
+bin/cake upgrade rector --rules cakephp60
```
Run rector before updating your `composer.json` dependencies
@@ -33,9 +33,3 @@ to ensure the tool can resolve class names correctly.
- [6 0 Upgrade Guide](6-0-upgrade-guide)
- [6 0 Migration Guide](6-0-migration-guide)
-- [5 0 Upgrade Guide](5-0-upgrade-guide)
-- [5 0 Migration Guide](5-0-migration-guide)
-- [5 1 Migration Guide](5-1-migration-guide)
-- [5 2 Migration Guide](5-2-migration-guide)
-- [5 3 Migration Guide](5-3-migration-guide)
-- [5 4 Migration Guide](5-4-migration-guide)
diff --git a/docs/en/console-commands/commands.md b/docs/en/console-commands/commands.md
index 55cb26ebd8..4c17d46782 100644
--- a/docs/en/console-commands/commands.md
+++ b/docs/en/console-commands/commands.md
@@ -27,9 +27,9 @@ use Cake\Console\ConsoleIo;
class HelloCommand extends Command
{
- public function execute(Arguments $args, ConsoleIo $io): int
+ public function execute(): int
{
- $io->out('Hello world.');
+ $this->io->out('Hello world.');
return static::CODE_SUCCESS;
}
@@ -71,10 +71,10 @@ class HelloCommand extends Command
return $parser;
}
- public function execute(Arguments $args, ConsoleIo $io): int
+ public function execute(): int
{
- $name = $args->getArgument('name');
- $io->out("Hello {$name}.");
+ $name = $this->args->getArgument('name');
+ $this->io->out("Hello {$name}.");
return static::CODE_SUCCESS;
}
@@ -131,13 +131,13 @@ protected function buildOptionParser(ConsoleOptionParser $parser): ConsoleOption
return $parser;
}
-public function execute(Arguments $args, ConsoleIo $io): int
+public function execute(): int
{
- $name = $args->getArgument('name');
- if ($args->getOption('yell')) {
+ $name = $this->args->getArgument('name');
+ if ($this->args->getOption('yell')) {
$name = mb_strtoupper($name);
}
- $io->out("Hello {$name}.");
+ $this->io->out("Hello {$name}.");
return static::CODE_SUCCESS;
}
@@ -187,12 +187,12 @@ class UserCommand extends Command
return $parser;
}
- public function execute(Arguments $args, ConsoleIo $io): int
+ public function execute(): int
{
- $name = $args->getArgument('name');
+ $name = $this->args->getArgument('name');
$user = $this->fetchTable()->findByUsername($name)->first();
- $io->out(print_r($user, true));
+ $this->io->out(print_r($user, true));
return static::CODE_SUCCESS;
}
@@ -209,12 +209,12 @@ to terminate execution:
```php
// ...
-public function execute(Arguments $args, ConsoleIo $io): int
+public function execute(): int
{
- $name = $args->getArgument('name');
+ $name = $this->args->getArgument('name');
if (mb_strlen($name) < 5) {
// Halt execution, output to stderr, and set exit code to 1
- $io->error('Name must be at least 4 characters long.');
+ $this->io->error('Name must be at least 4 characters long.');
$this->abort();
}
@@ -222,15 +222,15 @@ public function execute(Arguments $args, ConsoleIo $io): int
}
```
-You can also use `abort()` on the `$io` object to emit a message and code:
+You can also use `abort()` on the `$this->io` object to emit a message and code:
```php
-public function execute(Arguments $args, ConsoleIo $io): int
+public function execute(): int
{
- $name = $args->getArgument('name');
+ $name = $this->args->getArgument('name');
if (mb_strlen($name) < 5) {
// Halt execution, output to stderr, and set exit code to 99
- $io->abort('Name must be at least 4 characters long.', 99);
+ $this->io->abort('Name must be at least 4 characters long.', 99);
}
return static::CODE_SUCCESS;
@@ -354,9 +354,9 @@ The `TreeHelper` outputs an array as a tree structure. This is useful for
displaying filesystem directories or any hierarchical data:
```php
-public function execute(Arguments $args, ConsoleIo $io): int
+public function execute(): int
{
- $helper = $io->helper('Tree');
+ $helper = $this->io->helper('Tree');
$helper->output([
'src' => [
'Controller',
@@ -461,9 +461,9 @@ class UpdateTableCommand extends Command
return $parser;
}
- public function execute(Arguments $args, ConsoleIo $io): int
+ public function execute(): int
{
- $table = $args->getArgument('table');
+ $table = $this->args->getArgument('table');
$this->fetchTable($table)->updateQuery()
->set([
'modified' => new DateTime(),
@@ -561,11 +561,11 @@ class UpdateTableCommand extends Command
return $parser;
}
- public function execute(Arguments $args, ConsoleIo $io): int
+ public function execute(): int
{
- $table = $args->getArgument('table');
- if ($io->ask('Are you sure?', 'n', ['y', 'n']) !== 'y') {
- $io->error('You need to be sure.');
+ $table = $this->args->getArgument('table');
+ if ($this->io->ask('Are you sure?', 'n', ['y', 'n']) !== 'y') {
+ $this->io->error('You need to be sure.');
$this->abort();
}
$this->fetchTable($table)->updateQuery()
diff --git a/docs/en/development/routing.md b/docs/en/development/routing.md
index 208cdf46a9..166042e52d 100644
--- a/docs/en/development/routing.md
+++ b/docs/en/development/routing.md
@@ -24,7 +24,7 @@ this to your **config/routes.php** file:
```php
/** @var \Cake\Routing\RouteBuilder $routes */
-$routes->connect('/', ['controller' => 'Articles', 'action' => 'index']);
+$routes->connect(route: '/', defaults: ['controller' => 'Articles', 'action' => 'index']);
```
This will execute the index method in the `ArticlesController` when the
@@ -33,7 +33,7 @@ accept multiple parameters, this would be the case, for example of a route for
viewing an article's content:
```php
-$routes->connect('/articles/*', ['controller' => 'Articles', 'action' => 'view']);
+$routes->connect(route: '/articles/*', defaults: ['controller' => 'Articles', 'action' => 'view']);
```
The above route will accept any URL looking like `/articles/15` and invoke the
@@ -44,17 +44,17 @@ you wish, you can restrict some parameters to conform to a regular expression:
```php
// Using fluent interface
$routes->connect(
- '/articles/{id}',
- ['controller' => 'Articles', 'action' => 'view'],
+ route: '/articles/{id}',
+ defaults: ['controller' => 'Articles', 'action' => 'view'],
)
->setPatterns(['id' => '\d+'])
->setPass(['id']);
// Using options array
$routes->connect(
- '/articles/{id}',
- ['controller' => 'Articles', 'action' => 'view'],
- ['id' => '\d+', 'pass' => ['id']],
+ route: '/articles/{id}',
+ defaults: ['controller' => 'Articles', 'action' => 'view'],
+ options: ['id' => '\d+', 'pass' => ['id']],
);
```
@@ -83,9 +83,9 @@ parameters:
```php
// In routes.php
$routes->connect(
- '/upgrade',
- ['controller' => 'Subscriptions', 'action' => 'create'],
- ['_name' => 'upgrade'],
+ route: '/upgrade',
+ defaults: ['controller' => 'Subscriptions', 'action' => 'create'],
+ options: ['_name' => 'upgrade'],
);
use Cake\Routing\Router;
@@ -101,9 +101,9 @@ connected inside a scope will inherit the path/defaults from their wrapping
scopes:
```php
-$routes->scope('/blog', ['plugin' => 'Blog'], function (RouteBuilder $routes) {
- $routes->connect('/', ['controller' => 'Articles']);
-});
+$routes->scope(path: '/blog', callback: function (RouteBuilder $routes) {
+ $routes->connect(route: '/', defaults: ['controller' => 'Articles']);
+}, params: ['plugin' => 'Blog']);
```
The above route would match `/blog/` and send it to
@@ -128,9 +128,9 @@ some routes we'll use the `scope()` method:
use Cake\Routing\RouteBuilder;
use Cake\Routing\Route\DashedRoute;
-$routes->scope('/', function (RouteBuilder $routes) {
+$routes->scope(path: '/', callback: function (RouteBuilder $routes) {
// Connect the generic fallback routes.
- $routes->fallbacks(DashedRoute::class);
+ $routes->fallbacks(routeClass: DashedRoute::class);
});
```
@@ -143,15 +143,15 @@ The basic format for a route definition is:
```php
$routes->connect(
- '/url/template',
- ['targetKey' => 'targetValue'],
- ['option' => 'matchingRegex'],
+ route: '/url/template',
+ defaults: ['targetKey' => 'targetValue'],
+ options: ['option' => 'matchingRegex'],
);
```
The first parameter is used to tell the router what sort of URL you're trying to
control. The URL is a normal slash delimited string, but can also contain
-a wildcard (*) or [Route Elements](#route-elements). Using a wildcard tells the router
+a wildcard `*` or [Route Elements](#route-elements). Using a wildcard tells the router
that you are willing to accept any additional arguments supplied. Routes without
a `*` only match the exact template pattern supplied.
@@ -163,17 +163,17 @@ as a destination string. A few examples of route targets are:
```php
// Array target to an application controller
$routes->connect(
- '/users/view/*',
- ['controller' => 'Users', 'action' => 'view']
+ route: '/users/view/*',
+ defaults: ['controller' => 'Users', 'action' => 'view']
);
-$routes->connect('/users/view/*', 'Users::view');
+$routes->connect(route: '/users/view/*', defaults: 'Users::view');
// Array target to a prefixed plugin controller
$routes->connect(
- '/admin/cms/articles',
- ['prefix' => 'Admin', 'plugin' => 'Cms', 'controller' => 'Articles', 'action' => 'index']
+ route: '/admin/cms/articles',
+ defaults: ['prefix' => 'Admin', 'plugin' => 'Cms', 'controller' => 'Articles', 'action' => 'index']
);
-$routes->connect('/admin/cms/articles', 'Cms.Admin/Articles::index');
+$routes->connect(route: '/admin/cms/articles', defaults: 'Cms.Admin/Articles::index');
```
The first route we connect matches URLs starting with `/users/view` and maps
@@ -212,8 +212,8 @@ when you want to use an argument that included a `/` in it:
```php
$routes->connect(
- '/pages/**',
- ['controller' => 'Pages', 'action' => 'show']
+ route: '/pages/**',
+ defaults: ['controller' => 'Pages', 'action' => 'show']
);
```
@@ -225,8 +225,8 @@ compose the default route parameters:
```php
$routes->connect(
- '/government',
- ['controller' => 'Pages', 'action' => 'display', 5],
+ route: '/government',
+ defaults: ['controller' => 'Pages', 'action' => 'display', 5],
);
```
@@ -242,7 +242,8 @@ that:
```php
$routes->connect(
- '/cooks/{action}/*', ['controller' => 'Users']
+ route: '/cooks/{action}/*',
+ defaults: ['controller' => 'Users']
);
```
@@ -267,16 +268,16 @@ specific HTTP verbs simpler:
```php
// Create a route that only responds to GET requests.
$routes->get(
- '/cooks/{id}',
- ['controller' => 'Users', 'action' => 'view'],
- 'users:view',
+ template: '/cooks/{id}',
+ target: ['controller' => 'Users', 'action' => 'view'],
+ name: 'users:view',
);
// Create a route that only responds to PUT requests
$routes->put(
- '/cooks/{id}',
- ['controller' => 'Users', 'action' => 'update'],
- 'users:update',
+ template: '/cooks/{id}',
+ target: ['controller' => 'Users', 'action' => 'update'],
+ name: 'users:update',
);
```
@@ -308,14 +309,14 @@ will be treated as part of the parameter:
```php
$routes->connect(
- '/{controller}/{id}',
- ['action' => 'view'],
+ route: '/{controller}/{id}',
+ defaults: ['action' => 'view'],
)->setPatterns(['id' => '[0-9]+']);
$routes->connect(
- '/{controller}/{id}',
- ['action' => 'view'],
- ['id' => '[0-9]+'],
+ route: '/{controller}/{id}',
+ defaults: ['action' => 'view'],
+ options: ['id' => '[0-9]+'],
);
```
@@ -336,15 +337,15 @@ rewritten like so:
use Cake\Routing\Route\DashedRoute;
// Create a builder with a different route class.
-$routes->scope('/', function (RouteBuilder $routes) {
- $routes->setRouteClass(DashedRoute::class);
- $routes->connect('/{controller}/{id}', ['action' => 'view'])
+$routes->scope(path: '/', callback: function (RouteBuilder $routes) {
+ $routes->setRouteClass(routeClass: DashedRoute::class);
+ $routes->connect(route: '/{controller}/{id}', defaults: ['action' => 'view'])
->setPatterns(['id' => '[0-9]+']);
$routes->connect(
- '/{controller}/{id}',
- ['action' => 'view'],
- ['id' => '[0-9]+'],
+ route: '/{controller}/{id}',
+ defaults: ['action' => 'view'],
+ options: ['id' => '[0-9]+'],
);
});
```
@@ -367,7 +368,7 @@ e.g have URLs like `/demo` instead of `/home/demo`, you can do the
following:
```php
-$routes->connect('/{action}', ['controller' => 'Home']);
+$routes->connect(route: '/{action}', defaults: ['controller' => 'Home']);
```
If you would like to provide a case insensitive URL, you can use regular
@@ -375,8 +376,8 @@ expression inline modifiers:
```php
$routes->connect(
- '/{userShortcut}',
- ['controller' => 'Teachers', 'action' => 'profile', 1],
+ route: '/{userShortcut}',
+ defaults: ['controller' => 'Teachers', 'action' => 'profile', 1],
)->setPatterns(['userShortcut' => '(?i:principal)']);
```
@@ -384,8 +385,8 @@ One more example, and you'll be a routing pro:
```php
$routes->connect(
- '/{controller}/{year}/{month}/{day}',
- ['action' => 'index'],
+ route: '/{controller}/{year}/{month}/{day}',
+ defaults: ['action' => 'index'],
)->setPatterns([
'year' => '[12][0-9]{3}',
'month' => '0[1-9]|1[012]',
@@ -448,8 +449,8 @@ of `connect()`:
```php
$routes->connect(
- '/{lang}/articles/{slug}',
- ['controller' => 'Articles', 'action' => 'view'],
+ route: '/{lang}/articles/{slug}',
+ defaults: ['controller' => 'Articles', 'action' => 'view'],
)
// Allow GET and POST requests.
->setMethods(['GET', 'POST'])
@@ -481,7 +482,7 @@ same options (like `_host`, `_https`, or `_port`) to multiple routes
without repeating them:
```php
-$routes->scope('/api', function (RouteBuilder $routes) {
+$routes->scope(path: '/api', callback: function (RouteBuilder $routes) {
// Set default options for all routes in this scope
$routes->setOptions([
'_host' => 'api.example.com',
@@ -489,8 +490,8 @@ $routes->scope('/api', function (RouteBuilder $routes) {
]);
// These routes will automatically have _host and _https set
- $routes->get('/users', ['controller' => 'Users', 'action' => 'index']);
- $routes->get('/posts', ['controller' => 'Posts', 'action' => 'index']);
+ $routes->get(template: '/users', target: ['controller' => 'Users', 'action' => 'index']);
+ $routes->get(template: '/posts', target: ['controller' => 'Posts', 'action' => 'index']);
});
```
@@ -503,23 +504,23 @@ Options set via `setOptions()` are:
Example with nested scopes and overrides:
```php
-$routes->scope('/api', function (RouteBuilder $routes) {
+$routes->scope(path: '/api', callback: function (RouteBuilder $routes) {
$routes->setOptions(['_host' => 'api.example.com']);
// This route uses the default host
- $routes->get('/public', ['controller' => 'Public', 'action' => 'index']);
+ $routes->get(template: '/public', target: ['controller' => 'Public', 'action' => 'index']);
// This route overrides the default host
- $routes->get('/internal', [
+ $routes->get(template: '/internal', target: [
'controller' => 'Internal',
'action' => 'index',
'_host' => 'internal.example.com',
]);
// Nested scope inherits the default host
- $routes->scope('/v2', function (RouteBuilder $routes) {
+ $routes->scope(path: '/v2', callback: function (RouteBuilder $routes) {
// This also uses api.example.com
- $routes->get('/users', ['controller' => 'Users', 'action' => 'index']);
+ $routes->get(template: '/users', target: ['controller' => 'Users', 'action' => 'index']);
});
});
```
@@ -545,10 +546,10 @@ public function view($articleId = null, $slug = null)
}
// routes.php
-$routes->scope('/', function (RouteBuilder $routes) {
+$routes->scope(path: '/', callback: function (RouteBuilder $routes) {
$routes->connect(
- '/blog/{id}-{slug}', // For example, /blog/3-CakePHP_Rocks
- ['controller' => 'Blogs', 'action' => 'view'],
+ route: '/blog/{id}-{slug}', // For example, /blog/3-CakePHP_Rocks
+ defaults: ['controller' => 'Blogs', 'action' => 'view'],
)
// Define the route elements in the route template
// to prepend as function arguments. Order matters as this
@@ -615,16 +616,16 @@ option can be used in reverse routing to identify the route you want to use:
```php
// Connect a route with a name.
$routes->connect(
- '/login',
- ['controller' => 'Users', 'action' => 'login'],
- ['_name' => 'login'],
+ route: '/login',
+ defaults: ['controller' => 'Users', 'action' => 'login'],
+ options: ['_name' => 'login'],
);
// Name a verb specific route
$routes->post(
- '/logout',
- ['controller' => 'Users', 'action' => 'logout'],
- 'logout',
+ template: '/logout',
+ target: ['controller' => 'Users', 'action' => 'logout'],
+ name: 'logout',
);
// Generate a URL using a named route.
@@ -648,34 +649,34 @@ for the route names. CakePHP makes building up route names easier by allowing
you to define name prefixes in each scope:
```php
-$routes->scope('/api', ['_namePrefix' => 'api:'], function (RouteBuilder $routes) {
+$routes->scope(path: '/api', callback: function (RouteBuilder $routes) {
// This route's name will be `api:ping`
- $routes->get('/ping', ['controller' => 'Pings'], 'ping');
-});
+ $routes->get(template: '/ping', target: ['controller' => 'Pings'], name: 'ping');
+}, params: ['_namePrefix' => 'api:']);
// Generate a URL for the ping route
Router::url(['_name' => 'api:ping']);
// Use namePrefix with plugin()
-$routes->plugin('Contacts', ['_namePrefix' => 'contacts:'], function (RouteBuilder $routes) {
+$routes->plugin(name: 'Contacts', callback: function (RouteBuilder $routes) {
// Connect routes.
-});
+}, params: ['_namePrefix' => 'contacts:']);
// Or with prefix()
-$routes->prefix('Admin', ['_namePrefix' => 'admin:'], function (RouteBuilder $routes) {
+$routes->prefix(name: 'Admin', callback: function (RouteBuilder $routes) {
// Connect routes.
-});
+}, params: ['_namePrefix' => 'admin:']);
```
You can also use the `_namePrefix` option inside nested scopes and it works as
you'd expect:
```php
-$routes->plugin('Contacts', ['_namePrefix' => 'contacts:'], function (RouteBuilder $routes) {
- $routes->scope('/api', ['_namePrefix' => 'api:'], function (RouteBuilder $routes) {
+$routes->plugin(name: 'Contacts', callback: function (RouteBuilder $routes) {
+ $routes->scope(path: '/api', callback: function (RouteBuilder $routes) {
// This route's name will be `contacts:api:ping`
- $routes->get('/ping', ['controller' => 'Pings'], 'ping');
- });
-});
+ $routes->get(template: '/ping', target: ['controller' => 'Pings'], name: 'ping');
+ }, params: ['_namePrefix' => 'api:']);
+}, params: ['_namePrefix' => 'contacts:']);
// Generate a URL for the ping route
Router::url(['_name' => 'contacts:api:ping']);
@@ -696,11 +697,11 @@ can be enabled by using the `prefix` scope method:
```php
use Cake\Routing\Route\DashedRoute;
-$routes->prefix('Admin', function (RouteBuilder $routes) {
+$routes->prefix(name: 'Admin', callback: function (RouteBuilder $routes) {
// All routes here will be prefixed with `/admin`, and
// have the `'prefix' => 'Admin'` route element added that
// will be required when generating URLs for these routes
- $routes->fallbacks(DashedRoute::class);
+ $routes->fallbacks(routeClass: DashedRoute::class);
});
```
@@ -717,11 +718,11 @@ You can map the URL /admin to your `index()` action of pages controller using
following route:
```php
-$routes->prefix('Admin', function (RouteBuilder $routes) {
+$routes->prefix(name: 'Admin', callback: function (RouteBuilder $routes) {
// Because you are in the admin scope,
// you do not need to include the /admin prefix
// or the Admin route element.
- $routes->connect('/', ['controller' => 'Pages', 'action' => 'index']);
+ $routes->connect(route: '/', defaults: ['controller' => 'Pages', 'action' => 'index']);
});
```
@@ -729,11 +730,11 @@ When creating prefix routes, you can set additional route parameters using
the `$options` argument:
```php
-$routes->prefix('Admin', ['param' => 'value'], function (RouteBuilder $routes) {
+$routes->prefix(name: 'Admin', callback: function (RouteBuilder $routes) {
// Routes connected here are prefixed with '/admin' and
// have the 'param' routing key set.
- $routes->connect('/{controller}');
-});
+ $routes->connect(route: '/{controller}');
+}, params: ['param' => 'value']);
```
Note the additional route parameters will be added to all the connected routes defined
@@ -745,18 +746,18 @@ would be mapped to `my-prefix` in the URL. Make sure to set a path for such pref
if you want to use a different format like for example underscoring:
```php
-$routes->prefix('MyPrefix', ['path' => '/my_prefix'], function (RouteBuilder $routes) {
+$routes->prefix(name: 'MyPrefix', callback: function (RouteBuilder $routes) {
// Routes connected here are prefixed with '/my_prefix'
- $routes->connect('/{controller}');
-});
+ $routes->connect(route: '/{controller}');
+}, params: ['path' => '/my_prefix']);
```
You can define prefixes inside plugin scopes as well:
```php
-$routes->plugin('DebugKit', function (RouteBuilder $routes) {
- $routes->prefix('Admin', function (RouteBuilder $routes) {
- $routes->connect('/{controller}');
+$routes->plugin(name: 'DebugKit', callback: function (RouteBuilder $routes) {
+ $routes->prefix(name: 'Admin', callback: function (RouteBuilder $routes) {
+ $routes->connect(route: '/{controller}');
});
});
```
@@ -767,9 +768,9 @@ The connected route would have the `plugin` and `prefix` route elements set.
When defining prefixes, you can nest multiple prefixes if necessary:
```php
-$routes->prefix('Manager', function (RouteBuilder $routes) {
- $routes->prefix('Admin', function (RouteBuilder $routes) {
- $routes->connect('/{controller}/{action}');
+$routes->prefix(name: 'Manager', callback: function (RouteBuilder $routes) {
+ $routes->prefix(name: 'Admin', callback: function (RouteBuilder $routes) {
+ $routes->connect(route: '/{controller}/{action}');
});
});
```
@@ -835,10 +836,10 @@ Routes for [Plugins](../plugins) should be created using the `plugin()`
method. This method creates a new routing scope for the plugin's routes:
```php
-$routes->plugin('DebugKit', function (RouteBuilder $routes) {
+$routes->plugin(name: 'DebugKit', callback: function (RouteBuilder $routes) {
// Routes connected here are prefixed with '/debug-kit' and
// have the plugin route element set to 'DebugKit'.
- $routes->connect('/{controller}');
+ $routes->connect(route: '/{controller}');
});
```
@@ -846,19 +847,19 @@ When creating plugin scopes, you can customize the path element used with the
`path` option:
```php
-$routes->plugin('DebugKit', ['path' => '/debugger'], function (RouteBuilder $routes) {
+$routes->plugin(name: 'DebugKit', options: ['path' => '/debugger'], callback: function (RouteBuilder $routes) {
// Routes connected here are prefixed with '/debugger' and
// have the plugin route element set to 'DebugKit'.
- $routes->connect('/{controller}');
+ $routes->connect(route: '/{controller}');
});
```
When using scopes you can nest plugin scopes within prefix scopes:
```php
-$routes->prefix('Admin', function (RouteBuilder $routes) {
- $routes->plugin('DebugKit', function (RouteBuilder $routes) {
- $routes->connect('/{controller}');
+$routes->prefix(name: 'Admin', callback: function (RouteBuilder $routes) {
+ $routes->plugin(name: 'DebugKit', callback: function (RouteBuilder $routes) {
+ $routes->connect(route: '/{controller}');
});
});
```
@@ -906,8 +907,8 @@ with the following router connection:
```php
use Cake\Routing\Route\DashedRoute;
-$routes->plugin('ToDo', ['path' => 'to-do'], function (RouteBuilder $routes) {
- $routes->fallbacks(DashedRoute::class);
+$routes->plugin(name: 'ToDo', options: ['path' => 'to-do'], callback: function (RouteBuilder $routes) {
+ $routes->fallbacks(routeClass: DashedRoute::class);
});
```
@@ -916,17 +917,17 @@ $routes->plugin('ToDo', ['path' => 'to-do'], function (RouteBuilder $routes) {
Routes can match specific HTTP methods using the HTTP verb helper methods:
```php
-$routes->scope('/', function (RouteBuilder $routes) {
+$routes->scope(path: '/', callback: function (RouteBuilder $routes) {
// This route only matches on POST requests.
$routes->post(
- '/reviews/start',
- ['controller' => 'Reviews', 'action' => 'start'],
+ template: '/reviews/start',
+ target: ['controller' => 'Reviews', 'action' => 'start'],
);
// Match multiple verbs
$routes->connect(
- '/reviews/start',
- [
+ route: '/reviews/start',
+ defaults: [
'controller' => 'Reviews',
'action' => 'start',
]
@@ -953,17 +954,17 @@ Routes can use the `_host` option to only match specific hosts. You can use
the `*.` wildcard to match any subdomain:
```php
-$routes->scope('/', function (RouteBuilder $routes) {
+$routes->scope(path: '/', callback: function (RouteBuilder $routes) {
// This route only matches on http://images.example.com
$routes->connect(
- '/images/default-logo.png',
- ['controller' => 'Images', 'action' => 'default'],
+ route: '/images/default-logo.png',
+ defaults: ['controller' => 'Images', 'action' => 'default'],
)->setHost('images.example.com');
// This route only matches on http://*.example.com
$routes->connect(
- '/images/old-logo.png',
- ['controller' => 'Images', 'action' => 'oldLogo']
+ route: '/images/old-logo.png',
+ defaults: ['controller' => 'Images', 'action' => 'oldLogo']
)->setHost('*.example.com');
});
```
@@ -976,8 +977,8 @@ parameter when generating URLs:
```php
// If you have this route
$routes->connect(
- '/images/old-logo.png',
- ['controller' => 'Images', 'action' => 'oldLogo'],
+ route: '/images/old-logo.png',
+ defaults: ['controller' => 'Images', 'action' => 'oldLogo'],
)->setHost('images.example.com');
// You need this to generate a url
@@ -998,8 +999,8 @@ To handle different file extensions in your URLs, you can define the extensions
using the `Cake\Routing\RouteBuilder::setExtensions()` method:
```php
-$routes->scope('/', function (RouteBuilder $routes) {
- $routes->setExtensions(['json', 'xml']);
+$routes->scope(path: '/', callback: function (RouteBuilder $routes) {
+ $routes->setExtensions(extensions: ['json', 'xml']);
});
```
@@ -1020,11 +1021,11 @@ from the URL, and then parse what remains. If you want to create a URL such as
/page/title-of-page.html you would create your route using:
```php
-$routes->scope('/page', function (RouteBuilder $routes) {
- $routes->setExtensions(['json', 'xml', 'html']);
+$routes->scope(path: '/page', callback: function (RouteBuilder $routes) {
+ $routes->setExtensions(extensions: ['json', 'xml', 'html']);
$routes->connect(
- '/{title}',
- ['controller' => 'Pages', 'action' => 'view'],
+ route: '/{title}',
+ defaults: ['controller' => 'Pages', 'action' => 'view'],
)->setPass(['title']);
});
```
@@ -1057,18 +1058,18 @@ registered into the route collection:
use Cake\Http\Middleware\CsrfProtectionMiddleware;
use Cake\Http\Middleware\EncryptedCookieMiddleware;
-$routes->registerMiddleware('csrf', new CsrfProtectionMiddleware());
-$routes->registerMiddleware('cookies', new EncryptedCookieMiddleware());
+$routes->registerMiddleware(name: 'csrf', middleware: new CsrfProtectionMiddleware());
+$routes->registerMiddleware(name: 'cookies', middleware: new EncryptedCookieMiddleware());
```
Once registered, scoped middleware can be applied to specific
scopes:
```php
-$routes->scope('/cms', function (RouteBuilder $routes) {
+$routes->scope(path: '/cms', callback: function (RouteBuilder $routes) {
// Enable CSRF & cookies middleware
$routes->applyMiddleware('csrf', 'cookies');
- $routes->get('/articles/{action}/*', ['controller' => 'Articles']);
+ $routes->get(template: '/articles/{action}/*', target: ['controller' => 'Articles']);
});
```
@@ -1076,9 +1077,9 @@ In situations where you have nested scopes, inner scopes will inherit the
middleware applied in the containing scope:
```php
-$routes->scope('/api', function (RouteBuilder $routes) {
+$routes->scope(path: '/api', callback: function (RouteBuilder $routes) {
$routes->applyMiddleware('ratelimit', 'auth.api');
- $routes->scope('/v1', function (RouteBuilder $routes) {
+ $routes->scope(path: '/v1', callback: function (RouteBuilder $routes) {
$routes->applyMiddleware('v1compat');
// Define routes here.
});
@@ -1090,11 +1091,11 @@ In the above example, the routes defined in `/v1` will have 'ratelimit',
middleware applied to routes in each scope will be isolated:
```php
-$routes->scope('/blog', function (RouteBuilder $routes) {
+$routes->scope(path: '/blog', callback: function (RouteBuilder $routes) {
$routes->applyMiddleware('auth');
// Connect the authenticated actions for the blog here.
});
-$routes->scope('/blog', function (RouteBuilder $routes) {
+$routes->scope(path: '/blog', callback: function (RouteBuilder $routes) {
// Connect the public actions for the blog here.
});
```
@@ -1110,10 +1111,10 @@ be combined into groups. Once combined groups can be applied like middleware
can:
```php
-$routes->registerMiddleware('cookie', new EncryptedCookieMiddleware());
-$routes->registerMiddleware('auth', new AuthenticationMiddleware());
-$routes->registerMiddleware('csrf', new CsrfProtectionMiddleware());
-$routes->middlewareGroup('web', ['cookie', 'auth', 'csrf']);
+$routes->registerMiddleware(name: 'cookie', middleware: new EncryptedCookieMiddleware());
+$routes->registerMiddleware(name: 'auth', middleware: new AuthenticationMiddleware());
+$routes->registerMiddleware(name: 'csrf', middleware: new CsrfProtectionMiddleware());
+$routes->middlewareGroup(name: 'web', middleware: ['cookie', 'auth', 'csrf']);
// Apply the group
$routes->applyMiddleware('web');
@@ -1130,9 +1131,9 @@ to allow REST access to a recipe controller, we'd do something like this:
```php
// In config/routes.php...
-$routes->scope('/', function (RouteBuilder $routes) {
- $routes->setExtensions(['json']);
- $routes->resources('Recipes');
+$routes->scope(path: '/', callback: function (RouteBuilder $routes) {
+ $routes->setExtensions(extensions: ['json']);
+ $routes->resources(name: 'Recipes');
});
```
@@ -1152,7 +1153,7 @@ json and rss. These routes are HTTP Request Method sensitive.
> [!NOTE]
> The default for pattern for resource IDs only matches integers or UUIDs.
> If your IDs are different you will have to supply a regular expression pattern
-> via the `id` option, for example, `$builder->resources('Recipes', ['id' => '.*'])`.
+> via the `id` option, for example, `$builder->resources(name: 'Recipes', options: ['id' => '.*'])`.
The HTTP method being used is detected from a few different sources.
The sources in order of preference are:
@@ -1173,9 +1174,9 @@ sub-resources as well. Sub-resource routes will be prepended by the original
resource name and a id parameter. For example:
```php
-$routes->scope('/api', function (RouteBuilder $routes) {
- $routes->resources('Articles', function (RouteBuilder $routes) {
- $routes->resources('Comments');
+$routes->scope(path: '/api', callback: function (RouteBuilder $routes) {
+ $routes->resources(name: 'Articles', callback: function (RouteBuilder $routes) {
+ $routes->resources(name: 'Comments');
});
});
```
@@ -1199,9 +1200,9 @@ you have both nested and non-nested resource controllers you can use a different
controller in each context by using prefixes:
```php
-$routes->scope('/api', function (RouteBuilder $routes) {
- $routes->resources('Articles', function (RouteBuilder $routes) {
- $routes->resources('Comments', ['prefix' => 'Articles']);
+$routes->scope(path: '/api', callback: function (RouteBuilder $routes) {
+ $routes->resources(name: 'Articles', callback: function (RouteBuilder $routes) {
+ $routes->resources(name: 'Comments', options: ['prefix' => 'Articles']);
});
});
```
@@ -1221,7 +1222,7 @@ By default, CakePHP will connect 6 routes for each resource. If you'd like to
only connect specific resource routes you can use the `only` option:
```php
-$routes->resources('Articles', [
+$routes->resources(name: 'Articles', options: [
'only' => ['index', 'view'],
]);
```
@@ -1246,7 +1247,7 @@ routes. For example, if your `edit()` action is called `put()` you can
use the `actions` key to rename the actions used:
```php
-$routes->resources('Articles', [
+$routes->resources(name: 'Articles', options: [
'actions' => ['update' => 'put', 'create' => 'add'],
]);
```
@@ -1259,7 +1260,7 @@ instead of `create()`.
You can map additional resource methods using the `map` option:
```php
-$routes->resources('Articles', [
+$routes->resources(name: 'Articles', options: [
'map' => [
'deleteAll' => [
'action' => 'deleteAll',
@@ -1276,7 +1277,7 @@ can use the 'path' key inside the resource definition to customize the path
name:
```php
-$routes->resources('Articles', [
+$routes->resources(name: 'Articles', options: [
'map' => [
'updateAll' => [
'action' => 'updateAll',
@@ -1297,7 +1298,7 @@ Resource routes can be connected to controllers in routing prefixes by
connecting routes within a prefixed scope or by using the `prefix` option:
```php
-$routes->resources('Articles', [
+$routes->resources(name: 'Articles', options: [
'prefix' => 'Api',
]);
```
@@ -1310,8 +1311,8 @@ You can provide `connectOptions` key in the `$options` array for
`resources()` to provide custom setting used by `connect()`:
```php
-$routes->scope('/', function (RouteBuilder $routes) {
- $routes->resources('Books', [
+$routes->scope(path: '/', callback: function (RouteBuilder $routes) {
+ $routes->resources(name: 'Books', options: [
'connectOptions' => [
'routeClass' => 'ApiRoute',
]
@@ -1328,8 +1329,8 @@ would be **/blog-posts**.
You can specify an alternative inflection type using the `inflect` option:
```php
-$routes->scope('/', function (RouteBuilder $routes) {
- $routes->resources('BlogPosts', [
+$routes->scope(path: '/', callback: function (RouteBuilder $routes) {
+ $routes->resources(name: 'BlogPosts', options: [
'inflect' => 'underscore', // Will use ``Inflector::underscore()``
]);
});
@@ -1343,8 +1344,8 @@ By default, resource routes use an inflected form of the resource name for the
URL segment. You can set a custom URL segment with the `path` option:
```php
-$routes->scope('/', function (RouteBuilder $routes) {
- $routes->resources('BlogPosts', ['path' => 'posts']);
+$routes->scope(path: '/', callback: function (RouteBuilder $routes) {
+ $routes->resources(name: 'BlogPosts', options: ['path' => 'posts']);
});
```
@@ -1655,11 +1656,11 @@ header redirection if a match is found. The redirection can occur to
a destination within your application or an outside location:
```php
-$routes->scope('/', function (RouteBuilder $routes) {
+$routes->scope(path: '/', callback: function (RouteBuilder $routes) {
$routes->redirect(
- '/home/*',
- ['controller' => 'Articles', 'action' => 'view'],
- ['persist' => true]
+ route: '/home/*',
+ url: ['controller' => 'Articles', 'action' => 'view'],
+ options: ['persist' => true]
// Or ['persist'=>['id']] for default routing where the
// view action expects $id as an argument.
);
@@ -1673,8 +1674,8 @@ redirected to. You can redirect to external locations using
string URLs as the destination:
```php
-$routes->scope('/', function (RouteBuilder $routes) {
- $routes->redirect('/articles/*', 'http://google.com', ['status' => 302]);
+$routes->scope(path: '/', callback: function (RouteBuilder $routes) {
+ $routes->redirect(route: '/articles/*', url: 'http://google.com', options: ['status' => 302]);
});
```
@@ -1690,9 +1691,9 @@ off with a route that looks like:
```php
$routes->get(
- '/view/{id}',
- ['controller' => 'Articles', 'action' => 'view'],
- 'articles:view',
+ template: '/view/{id}',
+ target: ['controller' => 'Articles', 'action' => 'view'],
+ name: 'articles:view',
);
```
@@ -1713,13 +1714,13 @@ rework when URLs require more parameters:
use Cake\Routing\Route\EntityRoute;
// Create entity routes for the rest of this scope.
-$routes->setRouteClass(EntityRoute::class);
+$routes->setRouteClass(routeClass: EntityRoute::class);
// Create the route just like before.
$routes->get(
- '/view/{id}/{slug}',
- ['controller' => 'Articles', 'action' => 'view'],
- 'articles:view',
+ template: '/view/{id}/{slug}',
+ target: ['controller' => 'Articles', 'action' => 'view'],
+ name: 'articles:view',
);
```
@@ -1777,17 +1778,17 @@ option:
```php
$routes->connect(
- '/{slug}',
- ['controller' => 'Articles', 'action' => 'view'],
- ['routeClass' => 'SlugRoute'],
+ route: '/{slug}',
+ defaults: ['controller' => 'Articles', 'action' => 'view'],
+ options: ['routeClass' => 'SlugRoute'],
);
// Or by setting the routeClass in your scope.
-$routes->scope('/', function (RouteBuilder $routes) {
- $routes->setRouteClass('SlugRoute');
+$routes->scope(path: '/', callback: function (RouteBuilder $routes) {
+ $routes->setRouteClass(routeClass: 'SlugRoute');
$routes->connect(
- '/{slug}',
- ['controller' => 'Articles', 'action' => 'view'],
+ route: '/{slug}',
+ defaults: ['controller' => 'Articles', 'action' => 'view'],
);
});
```
@@ -1808,7 +1809,7 @@ option for each route. For example using:
```php
use Cake\Routing\Route\DashedRoute;
-$routes->setRouteClass(DashedRoute::class);
+$routes->setRouteClass(routeClass: DashedRoute::class);
```
will cause all routes connected after this to use the `DashedRoute` route class.
@@ -1827,7 +1828,7 @@ Calling fallbacks like so:
```php
use Cake\Routing\Route\DashedRoute;
-$routes->fallbacks(DashedRoute::class);
+$routes->fallbacks(routeClass: DashedRoute::class);
```
Is equivalent to the following explicit calls:
@@ -1835,8 +1836,8 @@ Is equivalent to the following explicit calls:
```php
use Cake\Routing\Route\DashedRoute;
-$routes->connect('/{controller}', ['action' => 'index'], ['routeClass' => DashedRoute::class]);
-$routes->connect('/{controller}/{action}/*', [], ['routeClass' => DashedRoute::class]);
+$routes->connect(route: '/{controller}', defaults: ['action' => 'index'], options: ['routeClass' => DashedRoute::class]);
+$routes->connect(route: '/{controller}/{action}/*', defaults: [], options: ['routeClass' => DashedRoute::class]);
```
> [!NOTE]