Models

The model construction process has been made lighter. Models associations are now lazy loaded, applications with lots of models and associations will see great time reductions in the bootstrap process.

Now models won't require a database connection in the construction process, database will be accessed for the first time only when a find operation is issued or information for one of the columns is required.

Model

  • saveMany() Saves multiple records for a single model
  • validateMany() Validates multiple records for a single model
  • saveAssociated() Saves a single model record with its associated data
  • validateAssociated Validates a single model record and its associated data
  • saveAll() method was split up in above methods. The saveMany() and saveAssociated() don't accept $options['validate'] 'only', use respective validation methods. Using saveAll() is not changed, but it will delegate out to the new methods. See ticket #1157

Validation

Your model validation array can now sprintf compatible place holders / conversion specifiers, which can be replaced by your rule params or your own arguments.

class Foo extends AppModel {
    public $validate = array(
        'title' => array(
            'minLength' => array(
                'rule' => array('minLength', 6),
                'message' => 'Minimum length allowed is %d chars',
                'last' => false
            ),
            'between' => array(
                'rule' => array('between', 5, 15),
                'message' => array('You may enter up to %s chars (minimum is %s chars)', 14, 6)
            )
        )
    );
}

So for the above validate array assuming both validation fail your $Foo->validationErrors array would be

array(
    'title' => array(
        'Minimum length allowed is 6 chars',
        'You may enter up to 14 chars (minimum is 6 chars)'
    )
)

Counter Cache

For belongsTo association the key 'counterCache' can now be an array allowing you to specify multiple cache counters per associated model. Eg.

class Posts extends AppModel {
    public $belongsTo = array(
        'User' => array(
            'counterCache' => array(
                true, //Will update default counter field User.posts_count and without any conditions
                'posts_published' => array('Post.published' => true)
            )
        ),
        'Category' => array(
            'counterCache' => array(
                'posts_cnt' //Will update the non-conventional field Category.posts_cnt
            )
        )
    );
}

The old syntax of specifying 'counterCache' as true or field name and the 'counterScope' key works as usual, so that here no backward compatibility break.

Behaviors

--

Helpers

HtmlHelper

  • getCrumbsList() Creates breadcrumb links wrapped in <li> elements. See #856
  • loadConfig() has moved from Helper to HtmlHelper class. This method now uses the new reader classes (see 2.0 Configure ) to load your config file. As optional you can pass the path as second parameter (app/config is default). To simply, you can set the configuration file (and the reader) in Controller::$helpers (example below) to load on helper constructor. In configuration file you can set the below keys:
    • tags Should be an array with key value;
    • minimizedAttributes Should be a list;
    • 'docTypes' Should be an array with key value;
    • attributeFormat Should be a string;
    • minimizedAttributeFormat Should be a string.

Example how to set configuration file on controller:

public $helpers = array(
    'Html' => array(
        'configFile' => array('config_file', 'php') // Option one: an array with filename and reader name
        'configFile' => 'config_file' // Option two: a string with filename. The PhpReader will be used
    )
);

FormHelper

  • FormHelper now supports all HTML5 input types and custom input types. Just use the input type you want as the method on the helper. For example $this->Form->range() would create an input with type = range.
  • postLink() and postButton() Creates link/button to access some page using HTTP method POST. With this, in your controller you can avoid some action, like delete, to be accessed by GET method.
  • select() with multiple = checkbox, now treats the 'id' attribute as a prefix for all the generated options.

Libs

CakeRequest

CakeRequest is a new class introduced in 2.0. It encapsulates commonly used request introspection methods and replaces the params array with a more useful object. Read more about CakeRequest

CakeResponse

CakeResponse is a new class introduced in 2.0. It encapsulates commonly used method and properties in the HTTP response your application generates. It consolidates several features in CakePHP. Read more about CakeResponse

CakeSession, SessionComponent

CakeSession and the SessionComponent have had a number of changes, see the session section for more information.

Router

Routes can return full urls

Route objects can now return full urls, and Router will not further modify them beyond adding the query string and fragment elements. For example this could be used to create routes to handle subdomains, or enabling https/http flags. An example of a route class that supports subdomains would be:


When creating links you could do the following to make links pointing at other subdomains.

echo $this->Html->link(
     'Other domain',
     array('subdomain' => 'test', 'controller' => 'posts', 'action' => 'add')
);

The above would create a link with http://test.localhost/posts/add as the url.

Xml

Xml has had a number of changes. Read more about Xml class

New Lib features

Configure readers

Configure can now be configured to load configuration files from a variety of sources and formats. The new Configure features section contains more information about the changes made to configure.

Configure::read() without any arguments allows you to read all values from configure, instead of just the debug value.

Error and exception handling

CakePHP 2.0 has had error and exception handling rebuilt, to be more flexible and give more power to developers.

String::wrap()

String::wrap() was added to help making fixed width formatting of text easier. Its used in Shells whenever you use Shell::wrapText()

debug()

debug() no longer outputs html in the console. Instead it makes output like the following

########## DEBUG ##########
Array
(
    [0] => test
)
###########################

This should improve readability of debug() on the command line.

Components

Components received a similar treatment to helpers and behvaiors, Component is now the base class for components. Read more about the component changes

RequestHandler

RequestHandler was heavily refactored do to the introduction of CakeRequest. These changes allowed for some new features to be introduced as well.

Automatic parsing of Accept headers

If a client sends a single Accept mime type that matches one of the extensions enabled in Router, RequestHandler will treat it the same an extension. This expands CakePHP's support for REST style endpoints. To use this feature start off by enabling extensions in config/routes.php

Router::parseExtensions('json', 'xml');

Once you have created layouts and views for your extensions, you will be able to visit a url like posts/view/1 and send Accept: application/json in the headers to receive the json version of that url.

CookieComponent

CookieComponent now supports http only cookies. You can enable their use by setting $this->Cookie->httpOnly = true;. Having http only cookies will make them unaccessible from the browser.

Security Component CSRF separation

CakePHP has has CSRF protection since 1.2. For 2.0 the existing CSRF has a new more paranoid mode, and is its own standalone feature. In the past CSRF features were coupled with form tampering safe-guards. Developers often disabled validatePost in order to do dynamic forms, disabling the CSRF protection at the same time. For 2.0 CSRF checking has been separated from form tampering giving you greater control.

Using CSRF protection in CakePHP 2.0

Simply by adding the SecurityComponent to your components array, you can benefit from the CSRF protection it provides. By default CSRF nonces are valid for 30 minutes. You can control how long tokens last by setting csrfExpires on the component.

$components = array(
    'Security' => array(
        'csrfExpires' => '+1 hour'
    )
);

You can also set this property in your controller's beforeFilter

function beforeFilter() {
    $this->Security->csrfExpires = '+1 hour';
    ...
}

The csrfExpires property can be any value that is compatible with strtotime(). By default the FormHelper will add a data[_Token][key] containing the CSRF token to every form when the component is enabled.

Handling missing or expired tokens

Missing or expired tokens are handled similar to in previous versions. The SecurityComponent's blackHoleCallback will be called, but with a 'csrf' parameter instead of 'auth' as in previous versions. This helps you better filter out CSRF token failures.

Using per-session tokens instead of one-time use tokens

By default a new CSRF token is generated for each request, and each token can only be used one. If a token is used twice, it will be blackholed. Sometimes, this behaviour is not desirable, as it can create issues with single page applications. You can toggle on longer, multi-use tokens by setting csrfUseOnce to false. This can be done in the components array, or in the beforeFilter of your controller.

var $components = array(
    'Security' => array(
        'csrfUseOnce' => false
    )
);

This will tell the component that you want to re-use a CSRF token until it expires. If you are having issues with expired tokens, this is a good balance between security and ease of use.

Disabling the CSRF protection

There may be cases where you want to disable CSRF protection on your forms for some reason. If you do want to disable this feature, you can set $this->Security->csrfCheck = false; in your beforeFilter or use the components array. By default CSRF protection is enabled, and configured to use one-use tokens.

Controller

Controllers now have access to request and response objects. You can read more about these objects on their specific pages.

Console

The console for CakePHP 2.0 was almost entirely rebuilt. Several new features as well as some backwards incompatible changes were made. Read more about console changes

Pagination

Pagination now provides a default maxLimit for pagination at 100.

This limit can be overridden with the paginate variable on Controller.

$this->paginate = array('maxLimit' => 1000);

This default is provided to prevent user URL manipulation causing excessive strain on the database for subsequent requests, where a user would edit the 'limit' parameter to a very large number.

Aliasing

You can now alias helpers, components and behaviors to use your class instead of a different one. This means that you can very easily make a MyHtml helper and not need to replace every instance of $this->Html in your views. To do this, pass the 'className' key along with your class, like you would with models.

public $helpers = array( 
    'Html' => array( 
        'className' => 'MyHtml' 
    ) 
);

Similarly, you can alias components for use in your controllers.

public $components = array( 
    'Email' => array( 
        'className' => 'QueueEmailer' 
    ) 
);

Calls to the Email component would call the QueueEmailer component instead. Finally, you can alias behaviors as well.

public $actsAs = array( 
    'Containable' => array( 
        'className' => 'SuperContainable' 
    ) 
);

Because of the way 2.0 utilizes collections and shares them across the application, any classes you alias will be used throughout your application. Whenever your application tries to access the alias, it will access your class. For instance, when we aliased the Html helper in the example above, any helpers that use the Html helper or elements that load the Html helper, will use MyHtml instead.

ConnectionManager

A new method ConnectionManager::drop() was added to allow removing connections at runtime

I18n

In the past model validation errors were hard to translate. One of the most common options was declaring the validation array inside the model constructor to be able to traslate each one. This is not required anymore, every message declared in the model validation array will be translated in the moment a field is invalidated, so when the message reaches the view, it will be already processed by the translation function.

A new model property validationDomain was introduced, to hint the CakePHP core on which translation domain it should use for validation messages. If none is declared, default will be used.

I18n Extract Task

The shell task responsible for parsing all files in your application to extract the translatable tokens gained a couple of features:

  • It is now possible to exclude all plugins in the application, this eases the task of extracting messages from the application only, while the plugin messages can be extracted subsequently to be able to use another domain.
  • In the same way it is possible to exclude plugins, you can also extract translatable strings from a single plugin. The shell will configure the correct input and output paths for you when specified a plugin name.
  • The extract shell will now take in account models in the application folder to extract the validation error messages declared statically in the $validate property. You can hint the task to put the extracted messages in a specific domain if you need to.
New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

Source available from github

Repository is at http://github.com/cakephp/cakephp

Creating a bug report

When creating a bug report, please include as much relevant information as possible. Please include code to reproduce the issue. Or even better, make a unit test. Either change an existing test or add a new test to show that the expected behavior is not occuring.

2.1.361% complete

 

Completed 30 of 49 tickets

Pages