4.3 Migration Guide

CakePHP 4.3 is an API compatible upgrade from 4.0. This page outlines the deprecations and features added in 4.3.

Upgrading to 4.3.0

You can can use composer to upgrade to CakePHP 4.3.0:

php composer.phar require --update-with-dependencies "cakephp/cakephp:^[email protected]"


4.3 introduces a few deprecations. All of these features will continue for the duration of 4.x but will be removed in 5.0. You can use the upgrade tool to automate updating usage of deprecated features:

bin/cake upgrade rector --rules cakephp43 <path/to/app/src>


This only updates CakePHP 4.3 changes. Make sure you apply CakePHP 4.2 changes first.

A new configuration option has been added to disable deprecations on a path by path basis. See Deprecation Warnings for more information.


  • Connection::supportsDynamicConstraints() was deprecated now that fixtures don’t try to dynamically drop and create constraints.


  • Using mutable datetime classes with DateTimeType and other time related type classes is deprecated. Hence methods DatetimeType::useMutable(), DatetimeType::useImmutable() and similar methods in other type classes are deprecated.

  • DriverInterface::supportsQuoting() and DriverInterface::supportSavepoints() are now deprecated in favor of DriverInterface::supports() which accepts feature constants defined in DriverInterface.

  • DriverInterface::supportsDynamicConstraints() was deprecated now that fixtures don’t try to dynamically drop and create constraints.


  • The datetime classes Time and Date are deprecated. Use their immutable alternatives FrozenTime and FrozenDate instead.


  • FileLog moved the dateFormat config option to DefaultFormatter.

  • ConsoleLog moved the dateFormat config option to DefaultFormatter.

  • SyslogLog moved the format config option to LegacySyslogFormatter. Defaults to DefaultFormatter now.


  • “Double pass” middlewares, i.e. classes with __invoke($request, $response, $next) method are deprecated. Instead use Closure with signature function($request, $handler) or classes which implement Psr\Http\Server\MiddlewareInterface instead.


  • Socket::$connected is deprecated. Use isConnected() instead.

  • Socket::$description is deprecated.

  • Socket::$encrypted is deprecated. Use isEncrypted() instead.

  • Socket::$lastError is deprecated. Use lastError() instead.


  • Query proxying all ResultSetInterface methods (including `CollectionInterface`), which forces fetching results and calls the proxied method on the results, is now deprecated. An example of the deprecated usage is $query->combine('id', 'title');. This should be updated to $query->all()->combine('id', 'title'); instead.

  • Passing a validator object to Table::save() via the validate option is deprecated. Define the validator within the table class or use setValidator() instead.

  • Association::setName() is deprecated. Association names should be defined when the association is.


  • Colon prefixed route placeholders like :controller are deprecated. Use braced placeholders like {controller} instead.


  • The components’ Controller.shutdown event callback has been renamed from shutdown to afterFilter to match the controller one. This makes the callbacks more consistent.


  • FormHelper methods’ non-associative options (e.g. ['disabled']) are now deprecated.

  • Second argument $merge of ViewBuilder::setHelpers() has been deprecated in favor of dedicated ViewBuilder::addHelpers() method to cleanly separate merge from overwrite operation.


  • TestFixture::$fields and TestFixture::$import are deprecated. You should convert your application to the new fixture system.

  • TestCase::$dropTables is deprecated. Dropping tables during a test run is not compatible with the new migration/schema dump based fixtures and will be removed in 5.0.

Behavior Changes

While the following changes do not change the signature of any methods they do change the semantics or behavior of methods.


  • cake i18n extract no longer has a --relative-paths option. This option is on by default now.


  • Configure::load() will now raise an exception when an invalid configuration engine is used.


  • ComparisonExpression no longer wraps generated IdentifierExpression sql in (). This affects Query::where() and anywhere else a ComparisonExpression is generated.


  • Switched ConnectionManager::alias() $alias and $source parameter names to match what they are. This only affects documentation and named parameters.


  • Http\Client now uses ini_get('user_agent') with ‘CakePHP’ as a fallback for its user-agent.


  • Aligned Entity::isEmpty() and Entity::hasValue() to treat ‘0’ as a non-empty value. This aligns the behavior with documentation and original intent.

  • TranslateBehavior entity validation errors are now set in the _translations.{lang} path instead of {lang}. This normalizes the entity error path with the fields used for request data. If you have forms that modify multiple translations at once, you may need to update how you render validation errors.

  • The types specified in function expressions now take precedence over default types set for columns when selecting columns. For e.g. using $query->select(['id' => $query->func()->min('id')]) the value for id in fetched entity will be float instead of integer.


  • Router::connect(), Router::prefix(), Router::plugin() and Router::scope() are deprecated. Use the corresponding non-static RouteBuilder methods instead.

  • RouteBuilder::resources() now generates routes that use ‘braced’ placeholders.


  • Validator::setProvider() now raises an exception when a non-object, non-string provider name is used. Previously there would be no error, but the provider would also not work.


  • The $vars parameter of ViewBuilder::build() is deprecated. Use setVar() instead.

Breaking Changes

Behind the API, some breaking changes are necessary moving forward. They usually only affect tests.


  • BaseLog::_getFormattedDate() and dateFormat config were removed since the message formatting logic was moved into log formatters.


  • TimeHelper::fromString() now returns an instance of FrozenTime instead of Time.

New Features


  • Controller::middleware() was added which allows you to define middleware for a single controller only. See Controller Middleware for more information.


  • Database mapping types can now implement Cake\Database\Type\ColumnSchemaAwareInterface to specify column sql generation and column schema reflection. This allows custom types handle non-standard columns.

  • Logged queries now use TRUE and FALSE for postgres, sqlite and mysql drivers. This makes it easier to copy queries and run them in an interactive prompt.

  • The DatetimeType can now convert request data from the user’s timezone to the application timezone. See Converting Request Data from the User’s Timezone for more information.

  • JsonType::setEncodingOptions() was added. This method lets you define json_encode() options for when the ORM serializes JSON when persisting data.

  • Added DriverInterface::supports() which consolidates all feature checks into one function. Drivers can support custom feature namees or any of the DriverInterface::FEATURE\_* constants.

  • Added DriverInterface::inTransaction() which reflects the status returned by PDO::inTranaction().


  • Form::execute() now accepts an $options parameter. This parameter can be used to choose which validator is applied or disable validation.

  • Form::validate() now accepts a $validator parameter which chooses the validation set to be applied.


  • The CspMiddleware now sets the cspScriptNonce and cspStyleNonce request attributes which streamlines the adoption of strict content-security-policy rules.

  • Client::addMockResponse() and clearMockResponses() were added.


  • Log engines now use formatters to format the message string before writing. This can be configured with the formatter config option. See the Logging Formatters section for more details.

  • JsonFormatter was added and can be set as the formatter option for any log engine.


  • Queries that contain() HasMany and BelongsToMany associations now propagate the status of result casting. This ensures that results from all associations are either cast with type mapping objects or not at all.

  • Table now includes label in the list of fields that are candidates for displayField defaults.

  • Added Query::whereNotInListOrNull() and QueryExpression::notInOrNull() for nullable columns since null != value is always false and the NOT IN test will always fail when the column is null.


  • IntegrationTestTrait::enableCsrfToken() now lets you use custom CSRF cookie/session key names.

  • HttpClientTrait was added to make writing HTTP mocks easier. See Testing for more information.

  • A new fixture system has been introduced. This fixture system separates schema and data enabling you to re-use your existing migrations to define test schema. The Fixture Upgrade guide covers how to upgrade.


  • HtmlHelper::script() and HtmlHelper::css() now add the nonce attribute to generated tags when the cspScriptNonce and cspStyleNonce request attributes are present.

  • FormHelper::control() will now populate the aria-invalid, aria-required, and aria-describedby attributes based on metadata from the validator. The aria-label attribute will be set if you disable the automatic label element and provide a placeholder.

  • ViewBuilder::addHelpers() has been added to cleanly separate merge from overwrite operation.