Validation
Before an entity's data ever reaches your database, CakePHP gives you a chance to check it. Validation rules live on the Table class — the same class you used to run finds and saves in the CRUD Operations page — and they run automatically every time you build an entity from request data. If a rule fails, the save is stopped before anything touches the database, and the entity tells you exactly which fields were rejected and why.
Where Validation Rules Live
Every Table class can define a validationDefault() method. CakePHP calls this method for you and
passes in a Validator object, which you build up by chaining rule methods onto it. You don't have
to call this method yourself — it's wired in automatically as part of the normal entity-building flow.
<?php
namespace App\Model\Table;
use Cake\ORM\Table;
use Cake\Validation\Validator;
class ArticlesTable extends Table
{
public function validationDefault(Validator $validator): Validator
{
// Rules are added here — see the worked example below
return $validator;
}
}
Chaining Rules on the Validator
The Validator object exposes one method per rule, and every method returns the validator itself,
so you chain call after call onto the same object. A few of the most common ones:
| Method | What it checks |
|---|---|
requirePresence('title') | The title key must be present in the submitted data at all |
notEmptyString('title') | title must not be left blank |
maxLength('title', 255) | title may not exceed 255 characters |
email('email') | email must be a validly formatted email address |
numeric('price') | price must contain only a numeric value |
A Worked Example: Validating Articles
Here's a realistic validationDefault() for the ArticlesTable from the CRUD and
Associations pages, requiring a title and body on every article and validating an optional contact email:
public function validationDefault(Validator $validator): Validator
{
$validator
->requirePresence('title', 'create')
->notEmptyString('title')
->maxLength('title', 255)
->requirePresence('body', 'create')
->notEmptyString('body')
->allowEmptyString('contact_email')
->email('contact_email');
return $validator;
}
Reading this top to bottom: title and body are both required only on create, must
not be empty strings, and title is capped at 255 characters. contact_email is
optional (allowEmptyString) but, when it is supplied, must look like a real email address.
ArticlesTable from the Models & the ORM page to try it.How Validation Runs Automatically
You don't call validationDefault() directly. It runs on its own whenever you build an entity
from an array of data — most commonly via patchEntity() or newEntity(), the
same methods used in the save flow covered on the CRUD Operations page. If a
rule fails, the entity is still returned to you, but save() refuses to write it and returns
false instead of the saved entity.
$article = $this->Articles->patchEntity($article, $this->request->getData());
if ($this->Articles->save($article)) {
// Validation passed and the row was written
} else {
// Validation failed — save() never touched the database
}
Checking for Errors After a Failed Save
When save() returns false, ask the entity itself what went wrong with
getErrors(). It returns an array keyed by field name, where each value is a list of
human-readable error messages for that field.
if (!$this->Articles->save($article)) {
$errors = $article->getErrors();
// $errors might look like:
// ['title' => ['_required' => 'This field is required']]
}
You can also check a single field with $article->getError('title'), which returns just that
field's error messages (or an empty array if that field is fine).
Displaying Errors in a View (a Preview)
Conceptually, a template can loop over getErrors() or check individual fields to show messages
next to the input that failed. In practice you'll rarely write this by hand: the next page introduces the
FormHelper, which reads these same validation errors off the entity and renders them next
to each field for you automatically.