The focus here is server-side first form validation — not generic admin advice, but what I actually shipped. Client-side validation is UX, not security. I explain why server-side validation comes first in every form I build.
Never Trust Browser Input
Client-side validation is UX, not security. I explain why server-side validation comes first in every form I build.
- PHP validation rules — applied directly to server-side first form validation.
- sanitisation — applied directly to server-side first form validation.
- error messages — applied directly to server-side first form validation.
- AJAX feedback — applied directly to server-side first form validation.
What the Solution Looked Like
The working version of Why I Validate Forms on Server Side First centred on PHP validation rules, sanitisation, error messages, and AJAX feedback. I avoided copying patterns from other modules unless they solved a problem this feature actually had.
Return Errors Users Can Fix
Representative code from the implementation — simplified for readability, but structurally what I deploy.
Strict input validation at the service boundary
<?php
declare(strict_types=1);
final class RecordService
{
public function create(array $input): array
{
$title = trim($input['title'] ?? '');
if ($title === '' || strlen($title) > 180) {
throw new InvalidArgumentException('Invalid title.');
}
$stmt = $this->db->prepare('INSERT INTO records (title) VALUES (?)');
$stmt->bind_param('s', $title);
$stmt->execute();
return ['id' => $stmt->insert_id];
}
}After Shipping: What Actually Mattered
Shipping server-side first form validation cleanly meant the next developer could extend it without untangling hidden coupling.
If I repeated this, I would write the regression checks earlier — especially around the failure paths users hit once, not the happy path.
Where I Would Begin Again
- Start with the exact problem statement for server-side first form validation — one sentence, no buzzwords.
- Prioritise PHP validation rules before polishing secondary UI details.
- Validate sanitisation under realistic data volume, not demo rows.