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:

MethodWhat 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.

Note: This is real, copy-ready CakePHP code, but this website's own project doesn't have CakePHP installed, so nothing here executes on this page. Paste it into your own 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.

Next: Head to Helpers to see how the FormHelper turns these validation errors into labeled inputs with error messages, with almost no extra code.