Skip to content

Validační systém

Minimalistická validace bez dependencies. Bez Rakit, bez frameworku – jen funkce a pravidla.

  • Pipe-separated rules (required|email|min:5)
  • Standardní pravidla (required, email, regex, int, numeric, min, max, range, in, phone_e164)
  • Support pro libphonenumber (E.164 formát)
  • Lokalizovatelné chybové zprávy

Základní použití

Helper funkce validation() pro jednoduché ověření jednoho pole:

use function Petrovo\Validation\validation;

// Vrací string|false: error message či false pokud OK
$error = validation('email', 'test@example.com', 'required|email');
if ($error === false) {
    echo "Email je validní";
} else {
    echo "Chyba: " . $error;
}

Vrácená hodnota: - false – validace proběhla OK - string – chybová zpráva (lokalizovatelná)


Plná validace více polí

Pro validaci celého formuláře použij Validator třídu:

use Petrovo\Validation\Validator;
use Petrovo\Validation\ValidationErrors;

$validator = new Validator([
    'email' => 'Email je povinný',
    'password' => 'Heslo je příliš krátké',
]);

$validation = $validator->make($_POST, [
    'email' => 'required|email',
    'password' => 'required|min:8',
]);

$validation->validate();

if ($validation->fails()) {
    $errors = $validation->errors();

    // Všechny chyby jako HTML
    $all = $errors->all('<span>:message</span>');

    // První chyba konkrétního pole
    $emailError = $errors->first('email');

    // První chyba každého pole
    $byField = $errors->firstOfAll();
}

Dostupná pravidla

required

Pole je povinné (ne null, ne prázdný string):

validation('name', 'John', 'required');  // false
validation('name', '', 'required');      // Chyba
validation('name', null, 'required');    // Chyba

nullable

Pole může být null/prázdné (skip ostatních pravidel):

validation('nickname', null, 'nullable|email');  // false
validation('nickname', 'test', 'nullable|email'); // false

email

Validní emailová adresa:

validation('email', 'test@example.com', 'required|email');  // false
validation('email', 'invalid', 'required|email');           // Chyba

regex

Validace regulárním výrazem (parametr):

// Jen alphanumerické a - _
validation('tag', 'my-tag_123', 'required|regex:/^[a-zA-Z0-9_-]+$/');  // false
validation('tag', 'my tag!', 'required|regex:/^[a-zA-Z0-9_-]+$/');     // Chyba

int

Celočíselná hodnota:

validation('age', '25', 'required|int');    // false
validation('age', '25.5', 'required|int');  // Chyba

numeric

Numerická hodnota (int nebo float):

validation('price', '19.99', 'required|numeric');  // false
validation('price', 'abc', 'required|numeric');    // Chyba

min

Minimální délka/hodnota:

validation('password', 'secret123', 'required|min:8');  // false
validation('password', 'pass', 'required|min:8');       // Chyba

max

Maximální délka/hodnota:

validation('username', 'john', 'required|max:20');    // false
validation('username', 'a'.str_repeat('b', 30), 'required|max:20');  // Chyba

range

Hodnota mezi min a max:

validation('quantity', '50', 'required|range:10,100');   // false
validation('quantity', '5', 'required|range:10,100');    // Chyba

in

Hodnota v seznamu (čárkou odděleno):

validation('status', 'draft', 'required|in:draft,published,archived');  // false
validation('status', 'pending', 'required|in:draft,published,archived'); // Chyba

phoneE164

Mezinárodní telefonní číslo v E.164 formátu (uses libphonenumber):

validation('phone', '+420777123456', 'required|phoneE164');  // false
validation('phone', '777123456', 'required|phoneE164');      // Chyba

E.164 formát: - Začíná + - Maximálně 15 číslic - Bez mezer/pomlček


Příklady pravidel (pipe-separated)

// Email
'required|email'

// Telefonní číslo
'required|phoneE164'

// Heslo (min 8 znaků)
'required|min:8'

// Username (3-20 znaků, alfanumerické + - _)
'required|min:3|max:20|regex:/^[a-zA-Z0-9_-]+$/'

// Cena (číselná, 0.01 až 1000)
'required|numeric|range:0.01,1000'

// Status (jeden z možných)
'required|in:draft,published,archived'

// Volitelný email (pokud vyplní, musí být validní)
'nullable|email'

Lokalizovaná chybová hlášení

$validator = new Validator([
    'email' => 'Email je povinný',
    'password' => 'Heslo je příliš krátké',
]);

$validation = $validator->make($_POST, [
    'email' => 'required|email',
    'password' => 'required|min:8',
]);

$validation->validate();

if ($validation->fails()) {
    $errors = $validation->errors();

    // Získej zprávu s vlastním textem
    echo $errors->first('email');      // "Email je povinný"
}

Poznámka: Pokud nenadefienuješ zprávu pro pole, defaultní je "[field] validation failed".


ValidationErrors API

all(string $format = ':message'): array

Všechny chyby jako flat array (s formátováním):

$errors->all();
// ['Email je povinný', 'Heslo je příliš krátké']

$errors->all('<li>:message</li>');
// ['<li>Email je povinný</li>', '<li>Heslo je příliš krátké</li>']

first(string $field): ?string

První chyba konkrétního pole:

$errors->first('email');      // "Email je povinný"
$errors->first('nonexistent'); // null

firstOfAll(): array

První chyba každého pole (asociativní):

$errors->firstOfAll();
// ['email' => 'Email je povinný', 'password' => 'Heslo je příliš krátké']

Praktické příklady

Formulář kontaktu

use Petrovo\Validation\Validator;

$validator = new Validator([
    'name' => 'Jméno je povinné',
    'email' => 'Email je povinný a musí být validní',
    'message' => 'Zpráva je povinná',
]);

$validation = $validator->make($_POST, [
    'name' => 'required|min:3',
    'email' => 'required|email',
    'message' => 'required|min:10',
]);

$validation->validate();

if ($validation->fails()) {
    return json_response(['success' => false, 'errors' => $validation->errors()->firstOfAll()]);
}

// Pokračuj se zpracováním...

Registrace uživatele

$validator = new Validator([
    'email' => 'Email je povinný',
    'password' => 'Heslo musí mít alespoň 8 znaků',
]);

$validation = $validator->make($_POST, [
    'email' => 'required|email',
    'password' => 'required|min:8',
    'phone' => 'nullable|phoneE164',  // volitelný
]);

$validation->validate();

if ($validation->fails()) {
    // Vrať chyby
    return response()->json([
        'success' => false,
        'errors' => $validation->errors()->firstOfAll()
    ], 422);
}

// Registruj uživatele...

Jak to funguje

Validator.php

$validator = new Validator($customMessages);
$validator->make($data, $rules);
$validator->validate();  // Spustí všechna pravidla

if ($validator->fails()) {
    $errors = $validator->errors();  // ValidationErrors objekt
}

Proces: 1. make() – nastav data a rules 2. validate() – projdi všechna pravidla 3. fails() – byla nějaká chyba? 4. errors() – vrátí ValidationErrors objekt

Pravidla (metody ruleXxx())

Každé pravidlo je privátní metoda: - ruleRequired() – check required - ruleEmail() – check email format - ruleMin(), ruleMax() – délka/hodnota - ruleRegex() – regex match - rulePhoneE164() – libphonenumber check

Pokud pravidlo vrátí false → chyba se přidá.

Pipe syntax

'required|email|min:8'

Splituje se na |: 1. requiredmethod = 'ruleRequired', param = null 2. emailmethod = 'ruleEmail', param = null 3. min:8method = 'ruleMin', param = '8'

Každé pravidlo se spustí postupně. Při první selhání se chyba zaznamenává a pokračuje se.


Rozšíření – Vlastní pravidla

Přidat nové pravidlo (add method to Validator):

// V core/Validation/Validator.php
private function ruleCustom(mixed $value, ?string $param): bool {
    // Tvoje logika
    return true; // nebo false
}

Pak lze použít:

validation('field', 'value', 'required|custom:param');

Reálný příklad – Kontaktní formulář

Aplikace v app/tags/form/contact/_validation.php:

use Petrovo\Session\Session;
use Petrovo\Validation\Validator;
use function Petrovo\Http\json;
use function Petrovo\I18n\translate;

$lang = $lang ?? DEFAULT_LANG;

// Lokalizované chybové zprávy
$validator = new Validator([
    'website_csrf' => translate('Chyba CSRF ochrany formuláře', $lang),
    'surname'       => translate('Nevyplněné příjmení', $lang),
    'email'         => translate('Nevyplněný nebo neplatný e-mail', $lang),
    'phone'         => translate('Nevyplněný telefon', $lang),
    'phone_e164'    => translate('Neplatný formát telefonu', $lang),
    'gdpr'          => translate('Nevyplněn souhlas se zpracováním osobních údajů', $lang),
]);

// Validační pravidla
$validation = $validator->make($_POST, [
    'website_csrf' => 'required',
    'surname'       => 'required',
    'email'         => 'required|email',
    'phone'         => 'required',
    'phone_e164'    => 'required|phoneE164',
    'gdpr'          => 'required',
]);

// Spustit validaci
$validation->validate();

// Zkontrolovat výsledek
if ($validation->fails()) {
    $errors = $validation->errors();

    // Formátuj chyby jako HTML <span>
    $errorMessages = $errors->all('<span>:message</span>');

    // Vrať JSON odpověď (AJAX)
    json([
        'success'  => false,
        'message'  => '',
        'messages' => $errorMessages,
        'csrf'     => Session::get('website_csrf'),
    ]);
    exit;
}

// Pokud validace projde → pokračuj se zpracováním

Klíčové body:

  • Chybové zprávy lokalizovány přes translate()
  • Kombinace pravidel: CSRF token + email + phone + GDPR checkbox
  • HTML formátování (<span>:message</span>) pro frontend
  • JSON response s novým CSRF tokenem (pro re-submit)

Bezpečnost

  • Žádné SQL injection – všechna pravidla pracují jen s hodnotami, ne SQL
  • Žádné XSS – chybové zprávy se předávají, formátuj je v šabloně
  • Type hintsmixed $value – bez assumptions o typu
  • CSRF ochrany – součást validace (website_csrf pole)