Skip to content

Upgrade CakePHP to 4.4#3284

Open
jiru wants to merge 142 commits into
devfrom
cakephp4
Open

Upgrade CakePHP to 4.4#3284
jiru wants to merge 142 commits into
devfrom
cakephp4

Conversation

@jiru
Copy link
Copy Markdown
Member

@jiru jiru commented Apr 28, 2026

Solves #3067 and adds some more unit tests. Also fixes 4.x deprecations so that updating to 5.x should be much easier when the time comes.

Breaking changes:

  • There is a new, separate encryption key to encrypt the remember_me cookie, so existing remember_me cookies will become invalid. Do we want to add some transition mechanism?

Things to do during deployment:

cblanken and others added 20 commits April 25, 2026 06:28
Setting `$config` is deprecated. Configurations files should instead return an array.
See https://book.cakephp.org/3/en/appendices/3-0-migration-guide.html#configure
Access to Helper::$request as a property is deprecated as of CakePHP 3.7
The getter `Helper->getRequest()` should be used instead.
See https://book.cakephp.org/3/en/appendices/3-7-migration-guide.html#deprecations

Following are some other deprecation warnings addressed while fixing the above.
- Request::param() is deprecated as of 3.4. Use Request::getParam() instead. See https://book.cakephp.org/3/en/appendices/3-4-migration-guide.html#request-response-deprecations
- ServerRequest::here() to be removed in 4.0.0. Use getRequestTarget() instead.

Note:
The SecurityComponent is deprecated and I believe SecurityHelper will need to be refactored
or removed entirely per the 4.0 Migration Guide (https://book.cakephp.org/4/en/appendices/4-0-migration-guide.html#component)
before migrating to CakePHP 5.x
See this StackOverflow post for more details: https://stackoverflow.com/a/61630537
This addresses the following CakePHP 3.x deprecation notice
> Accessing `params` as a property will be removed in 4.0.0. Use request->getParam() instead

See https://book.cakephp.org/3/en/appendices/3-4-migration-guide.html#request-response-deprecations for details
This commit addresses the following Form and FormHelper related 3.x deprecation warnings
- FormHelper::input() is deprecated. Use FormHelper::control() instead. See https://book.cakephp.org/3/en/appendices/3-4-migration-guide.html#other-deprecations.
- FormHelpter::create() should take `null` instead of a `string` or `bool` as the context when creating contextless forms. See https://book.cakephp.org/3/en/appendices/3-9-migration-guide.html#deprecations.
Fix the following deprecation warning
> Cake\Controller\Component\SecurityComponent::config() is deprecated. Use setConfig()/getConfig() instead.
I couldn't find the exact version this deprecation happens, but the SecurityComponent page
here (https://book.cakephp.org/3/en/controllers/components/security.html) implies `SecurityComponent::config()`
is deprecated after 3.4
Fix the following deprecation warning.
> Using Query::repository() as getter is deprecated. Use getRepository() instead
See https://book.cakephp.org/3/en/appendices/3-6-migration-guide.html#deprecations for details
> EventManager::attach() is deprecated. Use EventManager::on() instead.
See https://api.cakephp.org/3.0/class-Cake.Event.EventManager.html
> Router::parseNamedParams() is deprecated. 2.x backwards compatible named parameter support will be removed in 4.0
To continue to support legacy URLs using named parameters, the Router::parseNamedParams()
method has been inlined into the AppController with the deprecation warning removed.
Fix the following deprecation(s)
> Helper::$request is deprecated. Use $helper->getView()->getRequest() instead.
See https://book.cakephp.org/3/en/appendices/3-7-migration-guide.html#deprecations
> The ArrayAccess methods will be removed in 4.0.0.Use withParam() instead
See https://book.cakephp.org/3/en/appendices/3-4-migration-guide.html
> Accessing `data` as a property will be removed in 4.0.0. Use request->getData() instead.
See https://book.cakephp.org/3/en/appendices/3-4-migration-guide.html

Note: in a couple instances, an `isset()` call is replaced with with a `null` check
since `isset()` cannot be used on the result of an expression.
> ViewBuilder::autoLayout() is deprecated. Use ViewBuilder::enableAutoLayout() or ViewBuilder::isAutoLayoutEnable() instead.
See https://book.cakephp.org/3/en/appendices/3-4-migration-guide.html#deprecated-combined-get-set-methods
> Plugin::load() is deprecated. Use Application::addPlugin() instead. This method will be removed in 4.0.0
See https://book.cakephp.org/3/en/appendices/3-7-migration-guide.html#testsuite
Fix the following deprecation warnings:

> ValidatorAwareTrait::validator() is deprecated. Use ValidatorAwareTrait::getValidator()/setValidator() instead.
See https://book.cakephp.org/3/en/appendices/3-5-migration-guide.html#validation

> App\Model\Entity\Export::errors() is deprecated. Use setError()/getError() or setErrors()/getErrors() instead.
Missing from the migration guides but deprecated on the EntityInterface in 3.4.0 according to the source.
See https://github.com/cakephp/cakephp/blob/571fb867995ccfa4034ec5b66577f0ab2acd4429/src/Datasource/EntityInterface.php#L188

> Validator::errors() is deprecated. Renamed to Validator::validate().
See https://book.cakephp.org/3/en/appendices/3-9-migration-guide.html#deprecations

> App\Model\Table\ExportsTable::schema() is deprecated. Use setSchema()/getSchema() instead.
See https://book.cakephp.org/3/en/appendices/3-4-migration-guide.html#deprecated-combined-get-set-methods
> Response::header() is deprecated. Use `withHeader()`, `getHeaderLine()` and `getHeaders()` instead.
See https://book.cakephp.org/3/en/appendices/3-4-migration-guide.html#request-response-deprecations
> Declaring fixtures in underscored format in TestCase::$fixtures is deprecated.
Upper CamelCase/PascalCase is expected instead.
See https://book.cakephp.org/3/en/appendices/3-7-migration-guide.html#deprecations
This one was missed on my first pass. See commit 30b3b9c for other instances.
> The ArrayAccess methods will be removed in 4.0.0. Use getParam() instead.
See https://book.cakephp.org/3/en/appendices/3-4-migration-guide.html#request-response-deprecations
> Helper::$request is deprecated. Use $helper->getView()->getRequest() instead.
See https://book.cakephp.org/3/en/appendices/3-7-migration-guide.html#deprecations
See commit b52e47d for other instances
Fix the following deprecations
> App\Model\Entity\Sentence::dirty() is deprecated. Use setDirty()/isDirty() instead
> App\Model\Entity\Vocable::dirty() is deprecated. Use setDirty()/isDirty() instead
> App\Model\Entity\Sentence::errors() is deprecated. Use setError()/getError() or setErrors()/getErrors() instead.
@jiru jiru mentioned this pull request Apr 28, 2026
26 tasks
jiru added 9 commits April 28, 2026 09:07
Fixes the following warning:
> Deprecated Error: You are using a deprecated argument order for Cake\Validation\Validator::allowEmptyString. You should reverse the order of your `when` and `message` arguments so that they are `message, when`.
Fixes the following warning:
> App\Model\Table\SentenceCommentsTable::schema() is deprecated. Use setSchema()/getSchema() instead.
Fixes the following warning:
> Using `string` or `bool` for $context is deprecated, use `null` to make a context-less form.
Fixes the following warning:
> FormHelper::input() is deprecated. Use FormHelper::control() instead.
Fixes the following warning:
> ServerRequest::query() is deprecated. Use getQuery() or the PSR-7 getQueryParams() and withQueryParams() methods instead.
Fixes the following warning:
> Event::$subject is deprecated. Use Event::getSubject() instead.
Fixes the following warning:
> Email::setTemplate() is deprecated. Use $email->viewBuilder()->setTemplate() instead.
Fixes the following warning:
> QueryExpression::tieWith() is deprecated. Use QueryExpression::setConjunction()/getConjunction() instead.
Using CakePHP 4.x upgrade tool https://github.com/cakephp/upgrade:
> cake upgrade file_rename locales ../tatoeba2/
jiru added 19 commits May 12, 2026 14:31
composer require --update-with-dependencies "cakephp/cakephp:4.3.x"
Using CakePHP 4.x upgrade tool https://github.com/cakephp/upgrade:

> cake upgrade rector --rules cakephp43
This fixes the following warning after upgrading to CakePHP 4.3:

> The `Time` class has been deprecated. Use the immutable alternative `FrozenTime` instead
This allows to install a complete schema without adding triggers yet.
CakePHP 4.3 introduces a new fixture API that allows to split fixture
schema from fixture data, so we no longer need to manually keep fixture
schema and main code schema in sync, avoid bugs such as
a1c994b.

See https://book.cakephp.org/4.x/appendices/fixture-upgrade.html

The documentation mentions using \Migrations\TestSuite\Migrator to run
migrations, but I was not able to get it work because it always want to
drop all tables before applying migrations. As it turns out, Migrator is
just a silly wrapper around \Migrations\Migrations, so I simply used
Migrations directly instead.
With the new fixtures API of CakePHP 4.3,
data not gets automatically encoded into json.
With the new fixtures API of CakePHP 4.3, some more fixtures are necessary;
not because of their data, but because some tests are adding data to these
tables, so we need them to get truncated at the end, otherwise subsequent
tests will fail to insert fixture data with "duplicate primary key" errors.
With the new fixtures API of CakePHP 4.3,
we need to overload getFixtures() instead of calling loadFixtures().
With the new fixtures API of CakePHP 4.3,
the way to manually retrieve fixtures data changed.
This fixes the following warning after upgrading to CakePHP 4.3:

> QueryExpression::addCase() is deprecated, use case() instead.
The CakePHP 4.3 migration guide says:

> Colon prefixed route placeholders like `:controller` are deprecated.
> Use braced placeholders like `{controller}` instead.
Merge config/routes.php from skeleton app 4.x branch at
https://github.com/cakephp/app.
This fixes the following warning after upgrading to CakePHP 4.3:

> `Router::scope()` is deprecated, use the non-static method `RouteBuilder::scope()` instead.
This fixes the following warning after upgrading to CakePHP 4.3:

> "Double pass" middleware are deprecated. Use a `Closure` with the signature of `($request, $handler)` or a class which implements `Psr\Http\Server\MiddlewareInterface` instead.
This fixes warnings like this after upgrading to CakePHP 4.3:

> Calling result set method `toList()` directly on query instance is deprecated. You must call `all()` to retrieve the results first.
This was likely left broken after the migration to CakePHP 3.
In CakePHP 4.3, ModelAwareTrait::loadModel() is deprecated and we
should use LocatorAwareTrait::fetchTable() instead. fetchTable()
does not store the returned table in a class attribute, so we need
to either use the returned value directly, store it in a temporary
variable, or store it in an object property, depending on the context.
In controllers, we can also use $defaultTable to have it loaded in
an object property already.
jiru added 3 commits May 15, 2026 07:12
With the new fixtures API of CakePHP 4.3, migrations can now be run
either on the main database or on the test database. However, the Tupi
code migration was always connecting to the main database because
loadModel() uses the default database connection. To have it pick the
correct database, we need to get the migration’s connection object and
pass it down to the table locator.
Replacing Time with FrozenTime in a27c97a
left some things broken because we had different default formats configured
for Time and FrozenTime in bootstrap.php. We are not supposed to use Time
any more, only FrozenTime.
composer require --update-with-dependencies "cakephp/cakephp:4.4.x"
@jiru jiru mentioned this pull request May 16, 2026
3 tasks
jiru added 5 commits May 16, 2026 13:18
Using CakePHP 4.x upgrade tool https://github.com/cakephp/upgrade:

> cake upgrade rector --rules cakephp44
In CakePHP 4.4,
the ErrorHandler and ConsoleErrorHandler classes are now deprecated.
Fixes the following warning after upgrading to CakePHP 4.4:

> PHP Deprecated:  Debugger::addFormat() is deprecated.
This fixes broken test AudioControllerTest
::testPaginateRedirectsPageOutOfBoundsToLastPage_asGuest().

After updating to CakePHP 4.4, for some reason saveMany() is now
calling ->toArray() on all created entities, and this will create
virtual properties Audio::$download_url, which requires routes to be
loaded. I could have called ->loadRoutes(), but I prefer to keep the
tests light with this simple work around.
RequestHandlerComponent has been deprecated in CakePHP 4.4.
@jiru jiru changed the title Upgrade CakePHP to 4.x Upgrade CakePHP to 4.4 May 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants