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 modelvalidateMany()Validates multiple records for a single modelsaveAssociated()Saves a single model record with its associated datavalidateAssociatedValidates 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 #856loadConfig()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:tagsShould be an array with key value;minimizedAttributesShould be a list;- 'docTypes' Should be an array with key value;
attributeFormatShould be a string;minimizedAttributeFormatShould 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()andpostButton()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.
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.3—61% complete
Completed 30 of 49 tickets