CakePHP 3

CakePHP 1.3.0 released on April 24, 2010

CakePHP 3.0.0 released on March 22, 2015
Time to upgrade?
Cake3
What's changed?

Requirements
-
CakePHP 3.x supports PHP Version 5.4.16 and above (namespaces, traits, closures, anonymous functions, short syntax for array() [])
-
CakePHP 3.x requires the mbstring extension
-
CakePHP 3.x requires the intl extension. (Internationalization extension http://php.net/manual/en/book.intl.php)
Recommended
CakePHP should be installed with Composer
Cake3\WhatsChanged

Namespaces
In the PHP world, namespaces are designed to solve two problems:
-
Name collisions between code you create, and internal PHP classes/functions/constants or third-party classes/functions/constants.
- Ability to alias (or shorten) Extra_Long_Names designed to alleviate the first problem, improving readability of source code
Cake3\WhatsChanged\Namespaces

<?php
namespace Sport\Football;
use Sport\Team;
use Sport\Kit\Shirt;
use Sport\Kit\Shorts;
class Bologna extends Team
{
protected $shirt = null;
protected $shorts = null;
public function __construct()
{
$this->shirt = new Shirt(['red', 'blue']);
$this->shorts = new Shorts(['white']);
// I can also do
// new \Sport\Kit\Shirt(['red', 'blue']);
}
}
// or class Bologna extends \Sport\Team
Cake3\WhatsChanged\Namespaces

<?php
namespace Country\Italy\City;
use Sport\Football\Bologna as Bfc;
class Bologna
{
public $footballTeam = null;
public function __construct()
{
$this->footballTeam = new Bfc();
}
}
Cake3\WhatsChanged\Namespaces

Cake3\WhatsChanged\Traits
Traits
Traits are a mechanism for code reuse in single inheritance languages such as PHP.
A Trait is intended to reduce some limitations of single inheritance by enabling a developer to reuse sets of methods freely in several independent classes living in different class hierarchies.
A Trait is similar to a class, but only intended to group functionality in a fine-grained and consistent way. It is not possible to instantiate a Trait on its own.

<?php
namespace Log;
use Log\Log;
trait LogTrait
{
public function log($msg)
{
return Log::write($msg);
}
}
Cake3\WhatsChanged\Traits
<?php
namespace Country\Italy\City;
use Sport\Football\Bologna as Bfc;
use Log\LogTrait;
class Bologna
{
use LogTrait;
public $footballTeam = null;
public function __construct()
{
$this->footballTeam = new Bfc();
$this->log('Bfc created');
}
}

// --------- example 1 ---------------
$greeting = function () {
return 'Hello world';
}
// Call function
echo $greeting(); // Returns 'Hello world'
// --------- example 2 ---------------
// Create a user
$user = 'Bato';
// Create a Closure
$greeting = function () use ($user) {
echo "Hello $user";
};
// Greet the user
$greeting(); // Returns 'Hello Bato'
// --------- example 3 ---------------
// Set a multiplier
$multiplier = 3;
// Create a list of numbers
$numbers = [1,2,3,4];
// Use array_walk to iterate through the list and multiply
array_walk($numbers, function ($number) use ($multiplier) {
echo $number * $multiplier;
});
Cake3\WhatsChanged\Closures

Cake3\WhatsChanged\Composer
Composer
Dependency Manager for PHP.

https://getcomposer.org
http://packagist.org (Packagist is the main Composer repository)

Cake3\WhatsChanged\Composer
Dependency Manager
Composer is a tool for dependency management in PHP. It allows you to declare the dependent libraries your project needs and it will install them in your project for you.
Composer is not a package manager. Yes, it deals with "packages" or libraries, but it manages them on a per-project basis, installing them in a directory (e.g. vendor) inside your project. By default it will never install anything globally. Thus, it is a dependency manager.

Cake3\WhatsChanged\Composer
Declaring dependencies
All you need to do is create a composer.json file which describes the project's dependencies.
{
"require": {
"cakephp/cakephp": "~3.0"
}
}
It requires cakephp >= 3.0 < 4.0.0
To resolve and download dependencies, run the install command
$ composer install
All dependencies are located in vendor directory.

Cake3\WhatsChanged\Composer
Declaring dependencies
After installing the dependencies, Composer writes the list of the exact versions it installed into a composer.lock file.
This locks the project to those specific versions.
The install command checks if a lock file is present, and if it is, it downloads the versions specified there (regardless of what composer.json says).
This means that if any of the dependencies get a new version, you won't get the updates automatically. To update to the new version, use the update command.
$ composer update
This will fetch the latest matching versions (according to your composer.json file) and also update the lock file with the new version.

Cake3\WhatsChanged\Composer
Autoloading
Composer also prepares an autoload file that's capable of autoloading all of the classes in any of the libraries that it downloads.
You can even add your own code to the autoloader by adding an autoload field to composer.json
require 'vendor/autoload.php';
{
"autoload": {
"psr-4": {"Acme\\": "src/"}
}
}
- PSR-0 autoloading
- PSR-4 autoloading (recommended since it offers greater ease of use, no need to regenerate the autoloader when you add classes)
- classmap generation
- files includes
Composer will register a PSR-4 autoloader for the Acme namespace.

Cake3\WhatsChanged\Composer
composer.json of cakephp/app
{
"name": "cakephp/app",
"description": "CakePHP skeleton app",
"homepage": "http://cakephp.org",
"type": "project",
"license": "MIT",
"require": {
"php": ">=5.4.16",
"cakephp/cakephp": "~3.0",
"mobiledetect/mobiledetectlib": "2.*",
"cakephp/migrations": "~1.0",
"cakephp/plugin-installer": "*"
},
"require-dev": {
"psy/psysh": "@stable",
"cakephp/debug_kit": "~3.0",
"cakephp/bake": "~1.0"
},
"suggest": {
"phpunit/phpunit": "Allows automated tests to be run without system-wide install.",
"cakephp/cakephp-codesniffer": "Allows to check the code against the coding standards used in CakePHP."
},
"autoload": {
"psr-4": {
"App\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"App\\Test\\": "tests",
"Cake\\Test\\": "./vendor/cakephp/cakephp/tests"
}
},
"scripts": {
"post-install-cmd": "App\\Console\\Installer::postInstall",
"post-autoload-dump": "Cake\\Composer\\Installer\\PluginInstaller::postAutoloadDump"
},
"minimum-stability": "dev",
"prefer-stable": true
}

Cake3\WhatsChanged\Composer
Create new CakePHP app
$ composer create-project --prefer-dist cakephp/app myapp
It creates a new CakePHP app based on cakephp/app skeleton adding all required dependencies

Cake3\WhatsChanged\Conventions
Conventions
- CakePHP 3 adopts PSR-2 coding style conventions
- filenames match the class names, and follow the PSR-0 or PSR-4 standards for autoloading (PagesController => PagesController.php, ...)
- Table names corresponding to CakePHP models are plural and underscored
- Field names with two or more words are underscored: first_name
- Foreign keys in hasMany, belongsTo or hasOne relationships are recognized by default as the (singular) name of the related table followed by _id
- Join tables, used in BelongsToMany relationships between models, should be named after the model tables they will join, arranged in alphabetical order (apples_zebras rather than zebras_apples)
- View template files are named after the controller functions they display, in an underscored form
- By convention traits in CakePHP are suffixed with Trait so they are easily discernible from classes or interfaces

Cake3\WhatsChanged\ApplicationDirectoryLayout
Application directory layout
Refer to https://github.com/cakephp/app
The application directory layout has changed and now follows PSR-4. (http://www.php-fig.org/psr/psr-4/)
\<NamespaceName>(\<SubNamespaceNames>)*\<ClassName>
- The fully qualified class name MUST have a top-level namespace name, also known as a "vendor namespace"
- The fully qualified class name MAY have one or more sub-namespace names (corresponding to folders name and in which the namespace separators represent directory separators).
- The fully qualified class name MUST have a terminating class name.
For example src/Cache/Cache.php is namespaced as Cake\Cache\Cache

Cake3\WhatsChanged\ApplicationDirectoryLayout
app/
├── bin
├── config
├── logs
├── plugins
├── src
├── tests
├── tmp
├── vendor
├── webroot
├── composer.json
├── index.php
├── phpunit.xml.dist
└── README.md
holds the Cake console executables
holds the Configuration files
holds logs
holds the Cake plugins
is where your application’s files will be placed
holds temp files
holds the test cases
holds the app dependencies
is the public document root

Cake3\WhatsChanged\ApplicationDirectoryLayout
src
├── Console
├── Controller
│ └── Component
├── Locale
├── Model
│ ├── Behavior
│ ├── Entity
│ └── Table
├── Shell
├── Template
│ ├── Element
│ │ └── Flash
│ ├── Email
│ │ ├── html
│ │ └── text
│ ├── Error
│ ├── Layout
│ │ ├── Email
│ │ │ ├── html
│ │ │ └── text
│ │ └── rss
│ └── Pages
└── View
└── Helper

Cake3\WhatsChanged\ORM
ORM
CakePHP 3.0 features a new ORM that has been re-written from the ground up.
The new ORM solves several problems by having more specialized and focused classes.
In the past you would use Model and a Datasource for all operations.
Now the ORM is split into more layers:
- Cake\Database\Connection - Provides a platform independent way to create and use connections
- Cake\Database\Dialect - The classes in this namespace provide platform specific SQL
- Cake\Database\Type - Is the gateway class to CakePHP database type conversion system
- Cake\ORM\Table - The main entry point into the new ORM. Provides access to a single table
- Cake\ORM\Behavior - The base class for behaviors
- Cake\ORM\Query - A fluent object based query builder
- Cake\ORM\ResultSet - A collection of results that gives powerful tools for manipulating data in aggregate
- Cake\ORM\Entity - Represents a single row result.

Cake3\WhatsChanged\ORM\Table
Table
They handle many of the tasks that Model did in previous releases. Table classes handle tasks like
- Creating queries.
- Providing finders.
- Validating and saving entities.
- Deleting entities.
- Defining & accessing associations.
- Triggering callback events.
- Interacting with behaviors.
Table classes have a pluralized name i.e. ArticlesTable class refers to articles db table

Cake3\WhatsChanged\ORM\Entity
Entity
In previous versions of CakePHP the Model class returned dumb arrays that could not contain any logic or behavior.
For CakePHP 3.0, the ORM always returns object result sets unless you explicitly disable that feature.
Entities are created in one of two ways. Either by loading data from the database, or converting request data into entities.
Once created, entities allow you to manipulate the data they contain and persist their data by collaborating with table objects.

Cake3\WhatsChanged\ORM
Find returns a Query Object
Calling find on a table will not return the results immediately, but will return a Query object
-
It is possible to alter queries further, after calling find
-
It is possible to stack custom finders to append conditions, sorting, limit and any other clause to the same query before it is executed
$articles = TableRegistry::get('Articles');
$query = $articles->find();
$query->where(['author_id' => 1])->order(['title' => 'DESC']);
$query = $articles->find('approved')->find('popular');
$query->find('latest');

Cake3\WhatsChanged\ORM
-
You can compose queries one into the other to create subqueries easier than ever
- You can decorate queries with iterators and call methods without even touching the database
$query = $articles->find('approved');
$favoritesQuery = $article->find('favorites', ['for' => $user]);
$query->where(['id' => $favoritesQuery->select(['id'])]);
// No queries made in this example!
$results = $articles->find()
->order(['title' => 'DESC'])
->formatResults(function ($results) {
return $results->extract('title');
});
Queries can be seen as the result object, trying to iterate the query, calling toArray() or any method inherited from collection, will result in the query being executed and results returned to you.

Cake3\WhatsChanged\ORM
// 1.3
$article = $this->Article->find('first');
// 3.0
$article = $this->Articles->find()->first();
// 1.3
$article = $this->Article->find('first', array(
'conditions' => array('author_id' => 1)
));
// 3.0
$article = $this->Articles->find('all', [
'conditions' => ['author_id' => 1]
])->first();
// Can also be written
$article = $this->Articles->find()
->where(['author_id' => 1])
->first();
// This works in both CakePHP 1.3 and 3.0 but in 1.3 you have to use array() syntax
$articles = $this->Articles->find('all', [
'fields' => ['id', 'title'],
'conditions' => [
'OR' => ['title' => 'Cake', 'author_id' => 1],
'published' => true
],
'contain' => ['Authors'], // The only change! (notice plural)
'order' => ['title' => 'DESC'],
'limit' => 10,
]);
Examples 1.3 vs 3.0

Cake3\WhatSChanged\ORM
Recursive and ContainableBehavior Removed
In CakePHP 3.0 ContainableBehavior, recursive, bindModel, and unbindModel have all been removed.
Instead the contain() method has been promoted to be a core feature of the query builder.
Associations are only loaded if they are explicitly turned on.
// To only load data from the articles table
$query = $this->Articles->find('all');
// To load articles and their related authors you would do:
$query = $this->Articles->find('all')->contain(['Authors']);

Cake3\WhatsChanged\ORM
Other differences
- No afterFind callback. Replaced by formatResult and Map/Reduce
- Associations No Longer Defined as Properties
- hasAndBelongsToMany has been renamed to belongsToMany
- Validation No Longer Defined as a Property
- Support for composite primary keys.
What's new?

-
Event System
-
Request & Response objects
-
Exception handling
-
View cells
-
Interactive Console (REPL Read Eval Print Loop)
-
PHP Built in server
Cake3\WhatsNew
Request & Response objects

Cake3\WhatsNew\Network
The request and response objects provide an abstraction around HTTP requests and responses.
Request
On each request one Request is created and then passed by reference to the various layers of an application that use request data
By default is availabe in:
- Controllers
- Views
- Helpers
- Cells
- Components (through Controllers)
$this->request

Cake3\WhatsNew\Network\Request
In general it contains all that was in $this->params, $this->data,
path information as here, base, webroot
$this->request->params['controller']
$this->request->params('controller')
// Passed arguments
$this->request->pass;
$this->request['pass'];
$this->request->params['pass'];
// URL is /posts/index?page=1&sort=title
$this->request->query['page'];
//--------- data ---------------
// An input with a name attribute equal to 'MyModel[title]' is accessible at
$this->request->data('MyModel.title');
// You can also access the array of data, as an array:
$this->request->data['title'];
$this->request->data['comments'][1]['author'];
//--------- input ---------------
// Applications employing REST often exchange data in non-URL-encoded post bodies.
// You can read input data in any format using Network\Request::input()
// Get JSON encoded data submitted to a PUT/POST action
$data = $this->request->input('json_decode');
// Get Xml encoded data submitted to a PUT/POST action
$data = $this->request->input('Xml::build', ['return' => 'domdocument']);
//---------- $_ENV and $_SERVER ------------
// Get a value
$value = $this->request->env('HTTP_HOST');
// Set a value. Generally helpful in testing.
$this->request->env('REQUEST_METHOD', 'POST');

Cake3\WhatsNew\Network\Request
- Checking Request Conditions
- Access Session Data $this->request->session()
- Host and Domain Name
- Working With HTTP Methods & Headers
- Trusting Proxy Headers
- Checking Accept Headers

Cake3\WhatsNew\Network\Response
Response provides an interface to wrap the common response-related tasks such as:
- Sending headers for redirects.
- Sending content type headers.
- Sending any header.
- Sending the response body.
Response

Cake3\WhatsNew\ViewCells
View cells are small mini-controllers that can invoke view logic and render out templates.
Cells are ideal for building reusable page components that require interaction with models, view logic, and rendering logic.
To create a cell, define a class in src/View/Cell and a template in src/Template/Cell/.
View Cells
namespace App\View\Cell;
use Cake\View\Cell;
class InboxCell extends Cell
{
public function display()
{
$this->loadModel('Messages');
$unread = $this->Messages->find('unread');
$this->set('unread_count', $unread->count());
}
}

Cake3\WhatsNew\ViewCells
Cell templates have an isolated scope:
- does not share the same View instance as the one used to render template and layout
- they are unaware of any helper calls made
View Cells
<!-- src/Template/Cell/Inbox/display.ctp -->
<div class="notification-icon">
You have <?= $unread_count ?> unread messages.
</div>
Loading Cells
// Load an application cell calling display() method
$cell = $this->cell('Inbox');
// Load a plugin cell
$cell = $this->cell('Messaging.Inbox');
// Run the expanded() method on the Inbox cell
$cell = $this->cell('Inbox::expanded');
// passing arguments to a cell Inbox::recent($since)
$cell = $this->cell('Inbox::recent', ['since' => '-3 days']);
// render the cell
<?= $cell ?>
Interactive Console

Cake3\WhatsNew\InteractiveConsole
$ bin/cake console
Welcome to CakePHP v3.0.0 Console
---------------------------------------------------------------
App : App
Path: /Users/mark/projects/cakephp-app/src/
---------------------------------------------------------------
>>> $articles = Cake\ORM\TableRegistry::get('Articles');
// object(Cake\ORM\Table)(
//
// )
>>> $articles->find();
>>> Cake\Routing\Router::parse('/articles/view/1');
// [
// 'controller' => 'Articles',
// 'action' => 'view',
// 'pass' => [
// 0 => '1'
// ],
// 'plugin' => NULL
// ]
>>> Cake\Routing\Router::url(['controller' => 'Articles', 'action' => 'edit', 99]);
// '/articles/edit/99'
PHP Built in server

Cake3\WhatsNew\PHPBuiltInServer
$ bin/cake server
This will start PHP’s built-in webserver on port 8765.
Open up http://localhost:8765
Questions?

Cake3\Questions
Ask Paolo :)
https://slides.com/albertopagliarini/cakephp-3
CakePHP 3
By Alberto Pagliarini
CakePHP 3
- 5,775