Skip to content
Choose a tag to compare

CakePHP 3.0.0-RC1

@lorenzo lorenzo released this
· 18335 commits to 4.x since this release
Choose a tag to compare

The CakePHP core team is proud to announce the first release candidate for CakePHP 3.0.0.
It's been an intense time since our last beta release. We have been busy polishing most of the rough edges that we could find with the help of the community.

This polishing sprint meant a few breaking API breaking changes from beta3, specifically around the validation subsystem, due to many shortcomings found in the previous implementation.

Below the list of new features and changes that made it into 3.0.0-rc1:

Revamped Validation

The validation process was split into two stages. The first stage is a user-facing type of validation and has not changed since the last release except for where and when it is performed.

In previous versions you would do

$article = $this->Articles->newEntity($this->request->data);
$this->Articles->save($article, ['validate' => 'myCustomValidatorName']);

But now, user-facing validation is performed when creating the entity and not when saving it. This requires you to pass the validation option to either newEntity or patchEntity methods:

$article = $this->Articles->newEntity($this->request->data, [
    'validate' => 'myCustomValidatorName'

It is important to notice that fields that fail validation will not be copied into the resulting entity.

The second validation step, that we have called "application rules", is done when saving or deleting an entity. The rules checking step is meant to check application integrity, such as uniqueness of a column, arity or foreignKey constraints:

// In UsersTable.php

public function buildRules(RulesChecker $rules) {
    return $rules;

Application rules can also be used to enforce business logic constraints such as state machines, and workflow states.

The validate() and validateMany() methods have been removed from the Table class.

You can read more about the application rules system in the rules checker documentation.

New Error Pages

The error pages containing the exception stack traces have been redesigned to be easier to read and spot what caused the error originally. The new look was inspired by the Rails' better errors plugin

New Bake Plugin

The cake bake command is now a plugin. This will help us evolve its code at a higher pace and introduce new code generators and configuration options.

One important change concerning bake is that it now uses CakePHP's View system to render the templates. This means that it is possible to attach listeners to the Bake.beforeRender and Bake.afterRender events to modify bake's output.

Additionally, the templating syntax has changed to make them more readable. If you had your own bake templates in the past, they will need to be updated to use the new syntax which uses erb style tags. To get the Bake plugin run:

composer require cakephp/bake=dev-master --dev

And load it in your application bootstrap_cli.php file:


Table-less Forms

Due to popular request, there is now a Form object that is capable of defining a schema and validating form data without the use of ORM tables or entities:

public function add()
        $contact = new ContactForm();
        if ($this->request->is('post')) {
            if ($contact->execute($this->request->data)) {
                $this->Flash->success('We will get back to you soon.');
                return $this->redirect(['action' => 'add']);
            $this->Flash->error('There was a problem submitting your form.');
        $this->set('contact', $contact);

You can read more about them here

Adopted PSR-2

We have recently adopted the PSR-2 coding style standard for CakePHP and all the official plugins. You can read more about the reasoning in this blog post

ORM Related Improvements

  • Added Query::firstOrFail()
  • Allowing to change the joinType in TranslateBehavior
  • Implemented Table::addAssociations() to add multiple associations at once
  • Support for IS NOT operator
  • It is now possible to call matching() and contain() for the same association alias.

We'd like to thank again everyone who has contributed thoughts, code, documentation or feedback to 3.0 so far. Please help us find any issues or rough edges in the code by opening tickets in Github.