CakePHP 3 Cheatsheet by Codaxis Suggestions? Mistakes? Contact us!

Controllers

Controller actions

use Cake\Controller\Controller;
class PostsController extends Controller {
    public function view($id) {
        //Your code here
    }
}

Before filter

use Cake\Event\Event;
public function beforeFilter(Event $event) {
    parent::beforeFilter($event);
}

Setting view variables

// Setting one variable at a time
$this->set('color', 'pink');
$this->set('color', $color);

// Setting via compact()
$color1 = 'pink';
$color2 = 'red';
$this->set(compact('color1', 'color2'));

Retrieving post data

// Using $request->data array
$this->request->data['field'];

// Using $request->data() getter
$this->request->data('field');
$this->request->data('data.subfield');

Load additional model

$this->loadModel('Articles');

Redirecting

return $this->redirect([
    'controller' => 'myController',
    'action' => 'myAction'
]);

Pass variables to the action

return $this->redirect([
    'controller' => 'myController',
    'action' => 'myAction',
    $id
]);

Redirect to the referer page

return $this->redirect($this->referer());

View layouts

public function index() {
    $this->viewBuilder()->layout('admin'); // New in 3.1
    // or
    $this->layout = 'admin'; // Before 3.1

    //To load a layout from a plugin
    $this->viewBuilder()->layout('Admin.admin'); // New in 3.1
    // or
    $this->layout = 'Admin.admin'; // Before 3.1
}

Change the layout of the entire controller

//use Cake\Event\Event;
public function beforeFilter(Event $event) {
    parent::beforeFilter($event);
    $this->viewBuilder()->layout('admin'); // New in 3.1
    // or
    $this->layout = 'admin'; // Before 3.1
}

Helpers & Components

class RecipesController extends AppController {
    public $helpers = ['Form'];
    public $components = ['RequestHandler'];
}

Views

View variables

//Output a variable
echo $color;
echo $color->name;

Setting variables

//Views have a set method of their own
$this->set('activeMenuButton', 'posts');
echo $activeMenuButton;

View elements

echo $this->element('helpbox');

//Passing variables to the view element
echo $this->element('helpbox', [
	'helptext' => 'This is the helptext'
]);

//Load elements from a plugin
echo $this->element('Contacts.helpbox');

Page title

$this->assign('title', 'Your title');

//In your layout
$this->fetch('title');

Models

Tables

namespace App\Model\Table;
use Cake\ORM\Table;

class SitiosTable extends Table {
	//Code...
}

Attributes

class SitiosTable extends Table {
	public function initialize(array $config) {
		$this->table('sitios');
		$this->displayField('myField');
		$this->primaryKey('my_id');
		$this->tablePrefix('prefix_');
    }
}

Associations

class SitiosTable extends Table {
	public function initialize(array $config) {
        $this->belongsTo('Authors', [
			'className' => 'Authors',
			'foreignKey' => 'author_id',
			'joinType' => 'INNER',
		]);
		$this->hasMany('Tags');
		$this->hasOne('Categories');
		$this->hasAndBelongsToMany('Topics');
    }
}

Retrieve single row

$article = $this->Articles->get($id);

Find all

$query = $this->Articles->find('all');

Filter data

$query = $this->Articles->find('all');
$filtered = $query->where(['category_id' => 2);

Count results

$num = $filtered->count();

Full example

$articles = $this->Articles->find('all')
		->where(['category_id' => 1)
		->order(['created' => 'DESC'])
		->limit(10);

Find first

$query = $this->Articles->find('all', [
    'order' => ['Articles.created' => 'DESC']
]);
$row = $query->first();

Conditions to contain

$query = $articles->find()->contain([
    'Comments' => function ($q) {
       return $q
            ->select(['body', 'author_id'])
            ->where(['Comments.approved' => true]);
    }
]);

Validating

use Cake\Validation\Validator;
class ArticlesTable extends Table {

    public function validationDefault(Validator $validator) {
        $validator
            ->add('title', [
	            	'unique' => [
	            		'rule' => ['validateUnique', ['scope' => 'title']],
	            		'provider' => 'table',
	            		'message' => 'You already have an article with that title!'
	            	]
	            ])
            ->notEmpty('body', 'The body of your article cannot be empty')
            ->notEmpty('title', 'Give your article a title!');
        return $validator;
    }
}

Saving data

// In your controller
$article = $this->Articles->newEntity($this->request->data);
if ($this->Articles->save($article)) {
    // ...
}

Modify a field

$article = $this->Articles->find('all')->where(['id' => 2])->first();

$article->title = 'My new title';
$this->Articles->save($article);

Bulk update

$this->updateAll(['published' => true], ['published' => false]);

Deleting data

$entity = $this->Articles->find('all')->where(['id' => 2]);
$result = $this->Articles->delete($entity);

//Delete all
$this->Articles->deleteAll(['is_spam' => true]);

Emails

Load class

use Cake\Network\Email\Email;

Basic usage

$email = new Email('default');
$email->from(['me@example.com' => 'My Site'])
    ->to('you@example.com')
    ->subject('About')
    ->send('My message');

Configuring transport

// Sample smtp configuration.
Email::configTransport('gmail', [
    'host' => 'ssl://smtp.gmail.com',
    'port' => 465,
    'username' => 'my@gmail.com',
    'password' => 'secret',
    'className' => 'Smtp'
]);

Templated Emails

//src/Template/Email/html/welcome.ctp
//src/Template/Layout/Email/html/fancy.ctp
$email->template('welcome', 'fancy')

//Using templates from plugins
$email->template('Blog.new_comment', 'Blog.auto_message');

View vars

$email->viewVars(['value' => 12345]);

//in your email templates
<p>Here is your value: <b>echo $value</b></p>

Attachments

$Email->attachments([
    'photo.png' => [
        'file' => '/full/some_hash.png',
        'mimetype' => 'image/png',
        'contentId' => 'my-unique-id'
    ]
]);

Quick emails

Email::deliver('you@example.com', 'Subject', 'Message', ['from' => 'me@example.com']);

Forms

Creating a form

// $article should be an empty Article entity if you are in articles/add.
// If you are in articles/edit it should contain the article to be edited.
echo $this->Form->create($article);

Finishing a form

echo $this->Form->end();

Form method - Get

echo $this->Form->create($article, ['type' => 'get']);

Form method - File

// This is still a Post method, but Cake automatically includes proper enctype
echo $this->Form->create($article, ['type' => 'file']);

Form action

echo $this->Form->create($article, ['action' => 'login']);

Form action outside controller

// Used when the desired action is outside of the controller
echo $this->Form->create(null, [
    'url' => ['controller' => 'Articles', 'action' => 'publish']
]);

Input password

echo $this->Form->input('password', ['type' => 'password']);

Input file

echo $this->Form->input('file', ['type' => 'file']);

Input hidden

echo $this->hidden('id');

Input birthday

echo $this->Form->input('birth_dt', [
    'label' => 'Date of birth',
    'dateFormat' => 'DMY',
    'minYear' => date('Y') - 70,
    'maxYear' => date('Y') - 18,
]);

Input textarea

echo $this->Form->input('notes', ['type' => 'textarea', 'cols' => 10, 'rows' => 2]);

Input button

echo $this->Form->button('Add', ['class' => 'yourClass']);

Input checkbox

echo $this->Form->checkbox('published', ['hiddenField' => false]);

Input select

echo $this->Form->select('field',
    [1, 2, 3, 4, 5],
    ['empty' => '(choose one)']
);

Input radio button

$options = ['M' => 'Male', 'F' => 'Female'];
$attributes = ['legend' => false];
echo $this->Form->radio('gender', $options, $attributes);

Select year

echo $this->Form->year('purchased', [
    'minYear' => 2000,
    'maxYear' => date('Y')
]);

Select months

// Autopopulated with the months of the year. You can pass your own months via the attribute 'monthNames'
echo $this->Form->month('mob');

Select days

// Autopopulated with numerical values representing the days of the month
echo $this->Form->day('created');

Select hours

echo $this->Form->hour('created', [
    'format' => 12
]);

echo $this->Form->hour('created', [
    'format' => 24
]);

Select minutes

echo $this->Form->minute('created', [
    'interval' => 10
]);

HTML Helper

Charset UTF-8

echo $this->Html->charset();

Charset ISO-8859-1

echo $this->Html->charset('ISO-8859-1');

Linking to CSS

//By default looks for files in webroot/css/
echo $this->Html->css('forms');

//Loading css from plugins
echo $this->Html->css('DebugKit.toolbar.css');

Linking to multiple CSS

echo $this->Html->css(['forms', 'tables', 'menu']);

Favicon

echo $this->Html->meta(
    'favicon.ico',
    '/favicon.ico',
    ['type' => 'icon']
);

Meta Comments

echo $this->Html->meta(
    'Comments',
    '/comments/index.rss',
    ['type' => 'rss']
);

Meta Keywords

echo $this->Html->meta(
    'keywords',
    'enter any meta keyword here'
);

Meta Description

echo $this->Html->meta(
    'description',
    'enter any meta description here'
);

Doctype

echo $this->Html->docType();

Linking to images

echo $this->Html->image('cake_logo.png', ['alt' => 'CakePHP']);

//To load images from a plugin
echo $this->Html->image('DebugKit.icon.png');

Linking to images with full path

echo $this->Html->image('logo.png', ['fullBase' => true]);
echo $this->Html->image('recipes/6.jpg', [
    'alt' => 'Brownies',
    'url' => ['controller' => 'Recipes', 'action' => 'view', 6]
]);
echo $this->Html->link(
    'Enter',
    '/pages/home',
    ['class' => 'button', 'target' => '_blank']
);
echo $this->Html->link(
    'Dashboard',
    ['controller' => 'Dashboards', 'action' => 'index', '_full' => true]
);
echo $this->Html->link(
    'Delete',
    ['controller' => 'Recipes', 'action' => 'delete', 6],
    ['confirm' => 'Are you sure you wish to delete this recipe?'],
);
echo $this->Html->link(
    $this->Html->image('recipes/6.jpg', ['alt' => 'Brownies']),
    'recipes/view/6',
    ['escape' => false]
);

Linking to media

echo $this->Html->media('audio.mp3')
//<audio src="/files/audio.mp3"></audio>

echo $this->Html->media('video.mp4', [
     'fullBase' => true,
     'text' => 'Fallback text'
 ])
// Outputs:
// <video src="http://www.somehost.com/files/video.mp4">Fallback text</video>

$this->Html->media(
     ['video.mp4', ['src' => 'video.ogg', 'type' => "video/ogg; codecs='theora, vorbis'"]],
     ['autoplay']
 )
/*
<video autoplay="autoplay">
     <source src="/files/video.mp4" type="video/mp4"/>
     <source src="/files/video.ogg" type="video/ogg;
         codecs='theora, vorbis'"/>
 </video>
*/

Linking to javascript

$this->Html->script('scripts');

Linking to multiple javascript

echo $this->Html->script(['jquery', 'wysiwyg', 'scripts']);

Javascript to specific block

echo $this->Html->script('wysiwyg', ['block' => 'scriptBottom']);
//in your layout
echo $this->fetch('scriptBottom');

Nested Lists

$list = [
    'Languages' => [
        'English' => [
            'American',
            'Canadian',
            'British',
        [,
        'Spanish',
        'German',
    ]
];
echo $this->Html->nestedList($list);
/*
<ul>
    <li>Languages
        <ul>
            <li>English
                <ul>
                    <li>American</li>
                    <li>Canadian</li>
                    <li>British</li>
                </ul>
            </li>
            <li>Spanish</li>
            <li>German</li>
        </ul>
    </li>
</ul>

*/

Table headers

echo $this->Html->tableHeaders(['Date', 'Title', 'Active']);
/*
<tr>
    <th>Date</th>
    <th>Title</th>
    <th>Active</th>
</tr>
*/

echo $this->Html->tableHeaders(
    ['Date','Title','Active'],
    ['class' => 'status'],
    ['class' => 'product_table']
);
/*
<tr class="status">
     <th class="product_table">Date</th>
     <th class="product_table">Title</th>
     <th class="product_table">Active</th>
</tr>
*/

echo $this->Html->tableHeaders([
    'id',
    ['Name' => ['class' => 'highlight']],
    ['Date' => ['class' => 'sortable']]
]);
/*
<tr>
    <th>id</th>
    <th class="highlight">Name</th>
    <th class="sortable">Date</th>
</tr>
*/

Creating table cells

echo $this->Html->tableCells([
    ['Jul 7th, 2007', 'Best Brownies', 'Yes'],
    ['Jun 21st, 2007', 'Smart Cookies', 'Yes'],
    ['Aug 1st, 2006', 'Anti-Java Cake', 'No'],
]);
/*
<tr><td>Jul 7th, 2007</td><td>Best Brownies</td><td>Yes</td></tr>
<tr><td>Jun 21st, 2007</td><td>Smart Cookies</td><td>Yes</td></tr>
<tr><td>Aug 1st, 2006</td><td>Anti-Java Cake</td><td>No</td></tr>
*/

echo $this->Html->tableCells([
    ['Jul 7th, 2007', ['Best Brownies', ['class' => 'highlight']] , 'Yes'],
    ['Jun 21st, 2007', 'Smart Cookies', 'Yes'],
    ['Aug 1st, 2006', 'Anti-Java Cake', ['No', ['id' => 'special']]],
]);
/*
<tr>
    <td>
        Jul 7th, 2007
    </td>
    <td class="highlight">
        Best Brownies
    </td>
    <td>
        Yes
    </td>
</tr>
<tr>
    <td>
        Jun 21st, 2007
    </td>
    <td>
        Smart Cookies
    </td>
    <td>
        Yes
    </td>
</tr>
<tr>
    <td>
        Aug 1st, 2006
    </td>
    <td>
        Anti-Java Cake
    </td>
    <td id="special">
        No
    </td>
</tr>
*/

Paginator

Setting up

class ArticlesController extends AppController {
    public $components = ['Paginator'];
    public $paginate = [
        'limit' => 25,
        'order' => [
            'Articles.title' => 'asc'
        ]
    ];
}

Finding data

public function index() {
    $this->set('articles', $this->paginate());
}
public function index() {
    $query = $this->Articles->find('popular')->where(['author_id' => 1]);
    $this->set('articles', $this->paginate($query));
}

Using the paginator directly

$articles = $this->Paginator->paginate($articleTable, $config);

Maxlimit

// Limit the maximum number of rows that can be fetched (default: 100)
public $paginate = [
    'maxLimit' => 10
];
echo $this->Paginator->sort('user_id', 'User account');

Paginator Helper - Page numbers

echo $this->Paginator->numbers();

Paginator Helper - Page numbers limit

// In the example, display links to the first 2 pages and the last 2
echo $this->Paginator->numbers(['first' => 2, 'last' => 2]);

Paginator Helper - Previous, Next

echo $this->Paginator->prev(' << ' . __('previous'));
echo $this->Paginator->next(' >> ' . __('next'));

Paginator Helper - First, Last page

echo $this->Paginator->first('< first');
echo $this->Paginator->last('> last');

Routing

Basic usage

Router::connect('/articles/*', ['controller' => 'Articles', 'action' => 'view']);

Passing variables to the controller

Router::connect(
    '/articles/:id',
    ['controller' => 'Articles', 'action' => 'view'],
    ['id' => '\d+', 'pass' => ['id']]
);