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:^4.3"
Deprecations
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>NOTE
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
Connection::supportsDynamicConstraints()was deprecated now that fixtures don't try to dynamically drop and create constraints.
Controller
- The components'
Controller.shutdownevent callback has been renamed fromshutdowntoafterFilterto match the controller one. This makes the callbacks more consistent.
Database
- Using mutable datetime classes with
DateTimeTypeand other time related type classes is deprecated. Hence methodsDateTimeType::useMutable(),DateTimeType::useImmutable()and similar methods in other type classes are deprecated. DriverInterface::supportsQuoting()andDriverInterface::supportSavepoints()are now deprecated in favor ofDriverInterface::supports()which accepts feature constants defined inDriverInterface.DriverInterface::supportsDynamicConstraints()was deprecated now that fixtures don't try to dynamically drop and create constraints.
I18n
- The datetime classes
TimeandDateare deprecated. Use their immutable alternativesFrozenTimeandFrozenDateinstead.
Log
FileLogmoved thedateFormatconfig option toDefaultFormatter.ConsoleLogmoved thedateFormatconfig option toDefaultFormatter.SyslogLogmoved theformatconfig option toLegacySyslogFormatter. Defaults toDefaultFormatternow.
Middleware
- "Double pass" middlewares, i.e. classes with
__invoke($request, $response, $next)method are deprecated. Instead useClosurewith signaturefunction($request, $handler)or classes which implementPsr\Http\Server\MiddlewareInterfaceinstead.
Network
Socket::$connectedis deprecated. UseisConnected()instead.Socket::$descriptionis deprecated.Socket::$encryptedis deprecated. UseisEncrypted()instead.Socket::$lastErroris deprecated. UselastError()instead.
ORM
ModelAwareTrait::loadModel()is deprecated. Use the newLocatorAwareTrait::fetchTable()instead. For example, in controllers you can do$this->fetchTable()to get the default table instance or use$this->fetchTable('Foos')for a non-default table. You can set theLocatorAwareTrait::$defaultTableproperty to specify the default table alias forfetchTable(). But be aware thatLocatorAwareTrait::fetchTable()does not create a property with the name of the table alias on the calling object, e.g.$this->Articles, asModelAwareTrait::loadModel()does.- Query proxying all
ResultSetInterfacemethods (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 thevalidateoption is deprecated. Define the validator within the table class or usesetValidator()instead. Association::setName()is deprecated. Association names should be defined when the association is.QueryExpression::addCase()is deprecated. Usecase()instead. The['value' => 'literal']and['column' => 'identifier']syntax is not supported in the new fluent case builder, inserting raw SQL or identifiers requires to explicitly use expressions.
Routing
- Colon prefixed route placeholders like
:controllerare deprecated. Use braced placeholders like{controller}instead.
TestSuite
TestFixture::$fieldsandTestFixture::$importare deprecated. You should convert your application to the new fixture system.TestCase::$dropTablesis 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.
View
- FormHelper methods' non-associative options (for example,
['disabled']) are now deprecated. - Second argument
$mergeofViewBuilder::setHelpers()has been deprecated in favor of dedicatedViewBuilder::addHelpers()method to cleanly separate merge from overwrite operation.
Behavior Changes
While the following changes do not change the signature of any methods they do change the semantics or behavior of methods.
Collection
- Renamed
$preserveKeysparameter to$keepKeyswith same implementation.
Command
cake i18n extractno longer has a--relative-pathsoption. This option is on by default now.
Core
Configure::load()will now raise an exception when an invalid configuration engine is used.
Database
ComparisonExpressionno longer wraps generatedIdentifierExpressionsql in (). This affectsQuery::where()and anywhere else aComparisonExpressionis generated.- The SQLite implementation of
listTables()now returns tables and views. This change aligns SQLite with other database dialects.
Datasource
- Switched
ConnectionManager::alias()$aliasand$sourceparameter names to match what they are. This only affects documentation and named parameters.
Http
Http\Clientnow usesini_get('user_agent')with 'CakePHP' as a fallback for its user-agent.
ORM
- Aligned
Entity::isEmpty()andEntity::hasValue()to treat '0' as a non-empty value. This aligns the behavior with documentation and original intent. TranslateBehaviorentity 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 example, using
$query->select(['id' => $query->func()->min('id')])the value for id in fetched entity will be float instead of integer.
Routing
Router::connect(),Router::prefix(),Router::plugin()andRouter::scope()are deprecated. Use the corresponding non-staticRouteBuildermethods instead.RouteBuilder::resources()now generates routes that use 'braced' placeholders.
TestSuite
TestCase::deprecated()now asserts that at least one deprecation warning was triggered by the callback.
Validation
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.
View
- The
$varsparameter ofViewBuilder::build()is deprecated. UsesetVar()instead. HtmlHelper::script()andHtmlHelper::css()now escape absolute URLs that include a scheme.
Breaking Changes
Behind the API, some breaking changes are necessary moving forward. They usually only affect tests.
Log
BaseLog::_getFormattedDate()anddateFormatconfig were removed since the message formatting logic was moved into log formatters.
View
TimeHelper::fromString()now returns an instance ofFrozenTimeinstead ofTime.
New Features
Controller
Controller::middleware()was added which allows you to define middleware for a single controller only. See Controller Middleware for more information.- Controllers now support action parameters with
float,int,boolorarraytype declarations. Boolean passed parameters must be either0or1.
Core
deprecationWarning()no longer emits duplicate notices. Instead only the first instance of a deprecation will be displayed. This improves the readability of test output, and visual noise in an HTML context. You can restore duplicate notice output by setting theError.allowDuplicateDeprecationstotruein yourapp_local.php.- CakePHP's dependency on
league/containerwas bumped to^4.1.1. While the DI container is marked as experimental, this upgrade could require you to upgrade your service provider definitions.
Database
- Database mapping types can now implement
Cake\Database\Type\ColumnSchemaAwareInterfaceto specify column sql generation and column schema reflection. This allows custom types handle non-standard columns. - Logged queries now use
TRUEandFALSEfor postgres, sqlite and mysql drivers. This makes it easier to copy queries and run them in an interactive prompt. - The
DateTimeTypecan now convert request data from the user's timezone to the application timezone. See Converting Request Data From User Timezone for more information. JsonType::setEncodingOptions()was added. This method lets you definejson_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 names or any of the feature constants:FEATURE_CTEFEATURE_JSONFEATURE_QUOTEFEATURE_SAVEPOINTFEATURE_WINDOW
- Added
DriverInterface::inTransaction()which reflects the status returned byPDO::inTranaction(). - A fluent builder for
CASE, WHEN, THENstatements has been added. - The
listTablesWithoutViews()was added toSchemaCollectionand Driver Dialects. This method returns the list of tables excluding views. This is primarily used to truncate tables in tests.
Form
Form::execute()now accepts an$optionsparameter. This parameter can be used to choose which validator is applied or disable validation.Form::validate()now accepts a$validatorparameter which chooses the validation set to be applied.
Http
- The
CspMiddlewarenow sets thecspScriptNonceandcspStyleNoncerequest attributes which streamlines the adoption of strict content-security-policy rules. Client::addMockResponse()andclearMockResponses()were added.
Log
- Log engines now use formatters to format the message string before writing. This can be configured with the
formatterconfig option. See the Logging Formatters section for more details. JsonFormatterwas added and can be set as theformatteroption for any log engine.
ORM
- 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. Tablenow includeslabelin the list of fields that are candidates fordisplayFielddefaults.- Added
Query::whereNotInListOrNull()andQueryExpression::notInOrNull()for nullable columns sincenull != valueis always false and theNOT INtest will always fail when the column is null. LocatorAwareTrait::fetchTable()was added. This allows you to use$this->fetchTable()to get a table instance in classes which use the trait, like controllers, commands, mailers and cells. You can set theLocatorAwareTrait::$defaultTableproperty to specify the default table alias.
TestSuite
IntegrationTestTrait::enableCsrfToken()now lets you use custom CSRF cookie/session key names.HttpClientTraitwas added to make writing HTTP mocks easier. See Httpclient 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.
View
HtmlHelper::script()andHtmlHelper::css()now add thenonceattribute to generated tags when thecspScriptNonceandcspStyleNoncerequest attributes are present.FormHelper::control()will now populate thearia-invalid,aria-required, andaria-describedbyattributes based on metadata from the validator. Thearia-labelattribute 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.