Time to upgrade?
Cake3
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)
CakePHP should be installed with Composer
Cake3\WhatsChanged
In the PHP world, namespaces are designed to solve two problems:
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\TeamCake3\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 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
Dependency Manager for PHP.
https://getcomposer.org
http://packagist.org (Packagist is the main Composer repository)
Cake3\WhatsChanged\Composer
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
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 installAll dependencies are located in vendor directory.
Cake3\WhatsChanged\Composer
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 updateThis 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
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/"}
}
}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
$ composer create-project --prefer-dist cakephp/app myappIt creates a new CakePHP app based on cakephp/app skeleton adding all required dependencies
Cake3\WhatsChanged\Conventions
Cake3\WhatsChanged\ApplicationDirectoryLayout
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>
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
└── HelperCake3\WhatsChanged\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:
Cake3\WhatsChanged\ORM\Table
They handle many of the tasks that Model did in previous releases. Table classes handle tasks like
Table classes have a pluralized name i.e. ArticlesTable class refers to articles db table
Cake3\WhatsChanged\ORM\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
Calling find on a table will not return the results immediately, but will return a Query object
$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
$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
Event System
Request & Response objects
Exception handling
View cells
Interactive Console (REPL Read Eval Print Loop)
PHP Built in server
Cake3\WhatsNew
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:
$this->requestCake3\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
Cake3\WhatsNew\Network\Response
Response provides an interface to wrap the common response-related tasks such as:
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:
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 ?>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'Cake3\WhatsNew\PHPBuiltInServer
$ bin/cake serverThis will start PHP’s built-in webserver on port 8765.
Open up http://localhost:8765
Cake3\Questions
Ask Paolo :)
https://slides.com/albertopagliarini/cakephp-3