3.4 Migration Guide

CakePHP 3.4 is an API compatible upgrade from 3.3. This page outlines thechanges and improvements made in 3.4.

Minimum PHP 5.6 Required

CakePHP 3.4 requires at least PHP 5.6.0 as PHP 5.5 is no longer supported andwon’t receive any security fixes anymore.

Deprecations

The following is a list of deprecated methods, properties and behaviors. Thesefeatures will continue to function until 4.0.0 after which they will be removed.

Request & Response Deprecations

The bulk of deprecations for 3.4 are in the Request and Responseobjects. The existing methods that modify objects in-place are now deprecated,and superseded by methods that follow the immutable object patterns described inthe PSR-7 standard.

Several properties on Cake\Network\Request have been deprecated:

  • Request::$params is deprecated. Use Request::getAttribute('params') instead.
  • Request::$data is deprecated. Use Request::getData() instead.
  • Request::$query is deprecated. Use Request::getQueryParams() instead.
  • Request::$cookies is deprecated. Use Request::getCookie() instead.
  • Request::$base is deprecated. Use Request::getAttribute('base') instead.
  • Request::$webroot is deprecated. Use Request::getAttribute('webroot') instead.
  • Request::$here is deprecated. Use Request::getAttribute('here') instead.
  • Request::$_session was renamed to Request::$session.
    A number of methods on Cake\Network\Request have been deprecated:

  • get() & isset() methods are deprecated. Use getParam() instead.

  • method() is deprecated. Use getMethod() instead.
  • setInput() is deprecated. Use withBody() instead.
  • The ArrayAccess methods have all been deprecated.
  • Request::param() is deprecated. Use Request::getParam() instead.
  • Request::data() is deprecated. Use Request::getData() instead.
  • Request::query() is deprecated. Use Request::getQuery() instead.
  • Request::cookie() is deprecated. Use Request::getCookie() instead.
    Several methods on Cake\Network\Response have been deprecated because theyeither overlap the PSR-7 methods, or are made obsolete by the PSR-7 stack:

  • Response::header() is deprecated. Use getHeaderLine(), hasHeader() orResponse::getHeader() instead.

  • Response::body() is deprecated. Use Response::withBody() instead.
  • Response::statusCode() is deprecated. Use Response::getStatusCode() instead.
  • Response::httpCodes() This method should no longer be used. CakePHP now supports allstandards recommended status codes.
  • Response::protocol() is deprecated. Use Response::getProtocolVersion() instead.
  • send(), sendHeaders(), _sendHeader(), _sendContent(),_setCookies(), _setContentType(), and stop() are deprecated andmade obsolete by the PSR-7 HTTP stack.
    With responses heading towards immutable object patterns as recommended by thePSR-7 standards, a number of ‘helper’ methods in Response have beendeprecated and immutable variants are now recommended:

  • Response::location() would become Response::withLocation()

  • Response::disableCache() would become Response::withDisabledCache()
  • Response::type() would become Response::withType()
  • Response::charset() would become Response::withCharset()
  • Response::cache() would become Response::withCache()
  • Response::modified() would become Response::withModified()
  • Response::expires() would become Response::withExpires()
  • Response::sharable() would become Response::withSharable()
  • Response::maxAge() would become Response::withMaxAge()
  • Response::vary() would become Response::withVary()
  • Response::etag() would become Response::withEtag()
  • Response::compress() would become Response::withCompression()
  • Response::length() would become Response::withLength()
  • Response::mustRevalidate() would become Response::withMustRevalidate()
  • Response::notModified() would become Response::withNotModified()
  • Response::cookie() would become Response::withCookie()
  • Response::file() would become Response::withFile()
  • Response::download() would become Response::withDownload()
    Please see the Adopting Immutable Responses section for more informationbefore updating your code as using responses through the immutable methods willrequire additional changes.

Other Deprecations

  • The public properties on Cake\Event\Event are deprecated, new methods havebeen added to read/write the relevant properties.
  • Event::name() is deprecated. Use Event::getName() instead.
  • Event::subject() is deprecated. Use Event::getSubject() instead.
  • Event::result() is deprecated. Use Event::getResult() instead.
  • Event::data() is deprecated. Use Event::getData() instead.
  • The Auth.redirect session variable is no longer used. Instead a querystring parameter is used to store the redirect URL. This has the additionaleffect of removing the ability to store a redirect URL in the session outsideof login scenarios.
  • AuthComponent no longer stores redirect URLs when the unauthorized URL isnot a GET action.
  • The ajaxLogin option for AuthComponent is deprecated. You should use the403 status code to trigger the correct behavior in clientside code now.
  • The beforeRedirect method of RequestHandlerComponent is nowdeprecated.
  • The 306 status code in Cake\Network\Response is now deprecated and hasits status phrase changed to ‘Unused’ as this status code is non-standard.
  • Cake\Database\Schema\Table has been renamed toCake\Database\Schema\TableSchema. The previous name was confusing to a numberof users.
  • The fieldList option for Cake\ORM\Table::newEntity() andpatchEntity() has been renamed to fields to be more consistent withother parts of the ORM.
  • Router::parse() is deprecated. Router::parseRequest() should be usedinstead as it accepts a request and gives more control/flexibility in handlingincoming requests.
  • Route::parse() is deprecated. Route::parseRequest() should be usedinstead as it accepts a request and gives more control/flexibility in handlingincoming requests.
  • FormHelper::input() is deprecated. Use FormHelper::control() instead.
  • FormHelper::inputs() is deprecated. Use FormHelper::controls() instead.
  • FormHelper::allInputs() is deprecated. Use FormHelper::allControls() instead.
  • Mailer::layout() is deprecated. Use Mailer::setLayout() provided byMailer::__call() instead.

Deprecated Combined Get/Set Methods

In the past CakePHP has leveraged ‘modal’ methods that provide botha get/set mode. These methods complicate IDE autocompletion and our abilityto add stricter return types in the future. For these reasons, combined get/setmethods are being split into separate get and set methods.

The following is a list of methods that are deprecated and replaced withgetX() and setX() methods:

  • Cake\Core\InstanceConfigTrait
    • config()
  • Cake\Core\StaticConfigTrait
    • config()
    • dsnClassMap()
  • Cake\Console\ConsoleOptionParser
    • command()
    • description()
    • epilog()
  • Cake\Database\Connection
    • driver()
    • schemaCollection()
    • useSavePoints() (now enableSavePoints()/isSavePointsEnabled())
  • Cake\Database\Driver
    • autoQuoting (now enableAutoQuoting()/isAutoQuotingEnabled())
  • Cake\Database\Expression\FunctionExpression
    • name()
  • Cake\Database\Expression\QueryExpression
    • tieWith() (now setConjunction()/getConjunction())
  • Cake\Database\Expression\ValuesExpression
    • columns()
    • values()
    • query()
  • Cake\Database\Query
    • connection()
    • selectTypeMap()
    • bufferResults() (now enableBufferedResults()/isBufferedResultsEnabled())
  • Cake\Database\Schema\CachedCollection
    • cacheMetadata()
  • Cake\Database\Schema\TableSchema
    • options()
    • temporary() (now setTemporary()/isTemporary())
  • Cake\Database\TypeMap
    • defaults()
    • types()
  • Cake\Database\TypeMapTrait
    • typeMap()
    • defaultTypes()
  • Cake\ORM\Association
    • name()
    • cascadeCallbacks()
    • source()
    • target()
    • conditions()
    • bindingKey()
    • foreignKey()
    • dependent()
    • joinType()
    • property()
    • strategy()
    • finder()
  • Cake\ORM\Association\BelongsToMany
    • targetForeignKey()
    • saveStrategy()
    • conditions()
  • Cake\ORM\Association\HasMany
    • saveStrategy()
    • foreignKey()
    • sort()
  • Cake\ORM\Association\HasOne
    • foreignKey()
  • Cake\ORM\EagerLoadable
    • config()
    • setter part of canBeJoined() (now setCanBeJoined())
  • Cake\ORM\EagerLoader
    • matching() (getMatching() will have to be called after setMatching()to keep the old behavior)
    • autoFields() (now enableAutoFields()/isAutoFieldsEnabled())
  • Cake\ORM\Locator\TableLocator
    • config()
  • Cake\ORM\Query
    • eagerLoader()
    • hydrate() (now enableHydration()/isHydrationEnabled())
    • autoFields() (now enableAutoFields()/isAutoFieldsEnabled())
  • Cake\ORM\Table
    • table()
    • alias()
    • registryAlias()
    • connection()
    • schema()
    • primaryKey()
    • displayField()
    • entityClass()
  • Cake\Mailer\Email
    • from()
    • sender()
    • replyTo()
    • readReceipt()
    • returnPath()
    • to()
    • cc()
    • bcc()
    • charset()
    • headerCharset()
    • emailPattern()
    • subject()
    • template() (now setTemplate()/getTemplate() and setLayout()/getLayout())
    • viewRender() (now setViewRenderer()/getViewRenderer())
    • viewVars()
    • theme()
    • helpers()
    • emailFormat()
    • transport()
    • messageId()
    • domain()
    • attachments()
    • configTransport()
    • profile()
  • Cake\Validation\Validator
    • provider()
  • Cake\View\StringTemplateTrait
    • templates()
  • Cake\View\ViewBuilder
    • templatePath()
    • layoutPath()
    • plugin()
    • helpers()
    • theme()
    • template()
    • layout()
    • options()
    • name()
    • className()
    • autoLayout() (now enableAutoLayout()/isAutoLayoutEnabled())

Adopting Immutable Responses

Before you migrate your code to use the new response methods you should be awareof the conceptual differences the new methods have. The immutable methods aregenerally indicated using a with prefix. For example, withLocation().Because these methods operate in an immutable context, they return _new_instances which you need to assign to variables or properties. If you hadcontroller code that looked like:

  1. $response = $this->response;
  2. $response->location('/login')
  3. $response->header('X-something', 'a value');

If you were to simply find & replace method names your code would break. Insteadyou must now use code that looks like:

  1. $this->response = $this->response
  2. ->withLocation('/login')
  3. ->withHeader('X-something', 'a value');

There are a few key differences:

  • The result of your changes is re-assigned to $this->response. This iscritical to preserving the intent of the above code.
  • The setter methods can all be chained together. This allows you to skipstoring all the intermediate objects.

Component Migration Tips

In previous versions of CakePHP, Components often held onto references to boththe request and response, in order to make changes later. Before you adopt theimmutable methods you should use the response attached to the Controller:

  1. // In a component method (not a callback)
  2. $this->response->header('X-Rate-Limit', $this->remaining);
  3.  
  4. // Should become
  5. $controller = $this->getController();
  6. $controller->response = $controller->response->withHeader('X-Rate-Limit', $this->remaining);

In component callbacks you can use the event object to access theresponse/controller:

  1. public function beforeRender($event)
  2. {
  3. $controller = $event->getSubject();
  4. $controller->response = $controller->response->withHeader('X-Teapot', 1);
  5. }

Tip

Instead of holding onto references of Responses, always get the currentresponse from the controller, and re-assign the response property when youare done.

Behavior Changes

While these changes are API compatible, they represent minor variances inbehavior that may affect your application:

  • ORM\Query results will not typecast aliased columns based on the originalcolumn’s type. For example if you alias created to created_time youwill now get a Time object back instead of a string.
  • Internal ORM traits used to build Association classes have been removed andreplaced with new internal APIs. This shouldn’t impact your applications, butmay if you have created custom association types.
  • AuthComponent now uses a query string to store the redirect URL when anunauthenticated user is redirected to the login page. Previously, this redirectwas stored in the session. Using the query string allows for bettermulti-browser experience.
  • Database Schema reflection now treats unknown column types as string andnot text. A visible impact of this is that FormHelper will generatetext inputs instead of textarea elements for unknown column types.
  • AuthComponent no longer stores the flash messages it creates under the‘auth’ key. They are now rendered with the ‘error’ template under the‘default’ flash message key. This simplifies using AuthComponent.
  • Mailer\Email will now autodetect attachment content types usingmime_content_type if a content-type is not provided. Previouslyattachments would have defaulted to ‘application/octet-stream’.
  • CakePHP now uses the operator in place of call_user_func_array().If you are passing associative arrays, youshould update your code to pass a numerically indexed array usingarray_values() for the following methods:
    • Cake\Mailer\Mailer::send()
    • Cake\Controller\Controller::setAction()
    • Cake\Http\ServerRequest::is()

Visibility Changes

  • MailerAwareTrait::getMailer() will now become protected.
  • CellTrait::cell() will now become protected.
    If the above traits are used in controllers, their public methods could beaccessed by default routing as actions. These changes help protect yourcontrollers. If you need the methods to remain public you will need to updateyour use statement to look like:
  1. use CellTrait {
  2. cell as public;
  3. }
  4. use MailerAwareTrait {
  5. getMailer as public;
  6. }

Collection

  • CollectionInterface::chunkWithKeys() was added. User land implementationsof the CollectionInterface will need to implement this method now.
  • Collection::chunkWithKeys() was added.

Error

  • Debugger::setOutputMask() and Debugger::outputMask() were added. Thesemethods allow you to configure properties/array keys that should be maskedfrom output generated by Debugger (for instance, when calling debug()).

Event

  • Event::getName() was added.
  • Event::getSubject() was added.
  • Event::getData() was added.
  • Event::setData() was added.
  • Event::getResult() was added.
  • Event::setResult() was added.

I18n

Routing

  • RouteBuilder::prefix() now accepts an array of defaults to add to eachconnected route.
  • Routes can now match only specific hosts through the _host option.

Email

  • Email::setPriority()/Email::getPriority() have been added.

HtmlHelper

  • HtmlHelper::scriptBlock() no longer wraps the JavaScript code in <![CDATA[ ]]tag by default. The safe option which controls this behavior now defaultsto false. Using <![CDATA[ ]] tag was only required for XHTML which isno longer the dominant doctype used for HTML pages.

BreadcrumbsHelper

  • BreadcrumbsHelper::reset() was added. This method lets you clear outexisting crumbs.

PaginatorHelper

  • PaginatorHelper::numbers() now uses an HTML elipsis instead of ‘…’ inthe default templates.
  • PaginatorHelper::total() was added to enable reading the total number ofpages for the currently paginated results.
  • PaginatorHelper::generateUrlParams() was added as a lower level URLbuilding method.
  • PaginatorHelper::meta() can now create links for ‘first’, ‘last’.

FormHelper

  • You can now configure the sources which FormHelper reads from. This makescreating GET forms simpler. See Getting form values from the query string for moreinformation.
  • FormHelper::control() was added.
  • FormHelper::controls() was added.
  • FormHelper::allControls() was added.

Validation

  • Validation::falsey() and Validation::truthy() were added.

TranslateBehavior

  • TranslateBehavior::translationField() was added.

PluginShell

  • cake plugin load and cake plugin unload now support a —clioption, which updates the bootstrap_cli.php instead.

TestSuite

  • Support to PHPUnit 6 was added. With this framework version requiring PHP5.6.0 as a minimum version, the supported version of PHPUnit are now ^5.7|^6.0