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. required → method = 'ruleRequired', param = null
2. email → method = 'ruleEmail', param = null
3. min:8 → method = '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 hints –
mixed $value– bez assumptions o typu - CSRF ochrany – součást validace (website_csrf pole)