Validation Rules
Laravel Hyper provides custom validation rules for validating base64-encoded files from file inputs. These rules integrate with Laravel's validation system and use the same error message format as Laravel's native file validation rules.
Overview
When users select files with <input type="file" data-bind="avatar">, Datastar encodes them as base64 strings and sends them to the server in this format:
{
"avatar": [
"/9j/4AAQSkZJRgABAQAAAQ..." // Base64 string
]
}Hyper's validation rules handle this format automatically, validating the decoded file content.
File Validation Rules
b64file
Validate that the signal contains a valid base64-encoded file.
'document' => 'required|b64file'What it checks:
- Value is valid base64 format
- Can be successfully decoded
Usage:
signals()->validate([
'resume' => 'required|b64file',
'cover_letter' => 'nullable|b64file'
]);Error message: Uses Laravel's standard validation.file message
b64image
Validate that the signal contains a valid base64-encoded image.
'avatar' => 'required|b64image'What it checks:
- Value is valid base64 format
- Decoded content is a valid image (JPEG, PNG, GIF, WEBP, SVG, etc.)
- Uses PHP's
getimagesizefromstring()for validation
Usage:
signals()->validate([
'profile_picture' => 'required|b64image',
'banner' => 'nullable|b64image'
]);Error message: Uses Laravel's standard validation.image message
Size Validation Rules
b64max
Validate maximum file size in kilobytes.
b64max:sizeParameters:
size- Maximum file size in KB
Usage:
signals()->validate([
'avatar' => 'required|b64image|b64max:2048', // Max 2MB
'document' => 'required|b64file|b64max:5120' // Max 5MB
]);How size is calculated:
Base64 encoding increases file size by approximately 33%. Hyper decodes the base64 string and validates the original file size in KB.
Error message: Uses Laravel's standard validation.max.file message
b64min
Validate minimum file size in kilobytes.
b64min:sizeParameters:
size- Minimum file size in KB
Usage:
signals()->validate([
'presentation' => 'required|b64file|b64min:100' // At least 100KB
]);Error message: Uses Laravel's standard validation.min.file message
b64size
Validate exact file size in kilobytes.
b64size:sizeParameters:
size- Exact file size in KB
Usage:
signals()->validate([
'thumbnail' => 'required|b64image|b64size:50' // Exactly 50KB
]);Error message: Uses Laravel's standard validation.size.file message
Image Dimension Rules
b64dimensions
Validate image dimensions with flexible constraints.
b64dimensions:constraint1,constraint2,...Available constraints:
min_width=value- Minimum width in pixelsmax_width=value- Maximum width in pixelswidth=value- Exact width in pixelsmin_height=value- Minimum height in pixelsmax_height=value- Maximum height in pixelsheight=value- Exact height in pixelsratio=width/height- Aspect ratio (e.g.,16/9,3/2)
Usage:
Minimum dimensions:
signals()->validate([
'avatar' => 'required|b64image|b64dimensions:min_width=100,min_height=100'
]);Maximum dimensions:
signals()->validate([
'banner' => 'required|b64image|b64dimensions:max_width=1920,max_height=1080'
]);Exact dimensions:
signals()->validate([
'thumbnail' => 'required|b64image|b64dimensions:width=150,height=150'
]);Aspect ratio:
signals()->validate([
'cover_photo' => 'required|b64image|b64dimensions:ratio=16/9'
]);Combined constraints:
signals()->validate([
'profile_picture' => [
'required',
'b64image',
'b64dimensions:min_width=200,min_height=200,max_width=1000,max_height=1000,ratio=1/1'
]
]);Error message: Uses Laravel's standard validation.dimensions message
MIME Type Validation
b64mimes
Validate file extensions based on MIME type.
b64mimes:extension1,extension2,...Parameters:
- Comma-separated list of allowed file extensions
Supported extensions:
Images: jpg, jpeg, png, gif, webp, svg Documents: pdf, txt, csv, json
Usage:
Images only:
signals()->validate([
'avatar' => 'required|b64image|b64mimes:jpg,png,webp'
]);Documents:
signals()->validate([
'resume' => 'required|b64file|b64mimes:pdf,doc,docx'
]);Mixed types:
signals()->validate([
'attachment' => 'required|b64file|b64mimes:pdf,jpg,png,txt'
]);How it works:
- Decodes base64 content
- Detects MIME type using PHP's
finfo_buffer()(orgetimagesizefromstring()for images) - Maps MIME type to file extension
- Checks if extension is in allowed list
Error message: Uses Laravel's standard validation.mimes message
Combining Rules
All validation rules can be combined with standard Laravel validation rules:
Complete File Upload Validation
signals()->validate([
'avatar' => [
'required',
'b64image',
'b64max:2048',
'b64dimensions:min_width=100,min_height=100,max_width=500,max_height=500',
'b64mimes:jpg,png'
]
]);Multiple File Fields
signals()->validate([
'profile_picture' => 'required|b64image|b64max:2048|b64mimes:jpg,png',
'resume' => 'required|b64file|b64max:5120|b64mimes:pdf,doc,docx',
'cover_letter' => 'nullable|b64file|b64max:5120|b64mimes:pdf,doc,docx'
]);With Standard Laravel Rules
signals()->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users',
'avatar' => 'nullable|b64image|b64max:2048|b64mimes:jpg,png',
'bio' => 'nullable|string|max:1000'
]);Custom Error Messages
Use Laravel's custom error message syntax:
signals()->validate(
[
'avatar' => 'required|b64image|b64max:2048|b64dimensions:min_width=100'
],
[
'avatar.required' => 'Please upload a profile picture.',
'avatar.b64image' => 'The profile picture must be a valid image.',
'avatar.b64max' => 'The profile picture must not exceed 2MB.',
'avatar.b64dimensions' => 'The profile picture must be at least 100x100 pixels.'
]
);Common Patterns
Avatar Upload
public function uploadAvatar()
{
signals()->validate([
'avatar' => [
'required',
'b64image',
'b64max:2048',
'b64dimensions:min_width=100,min_height=100,max_width=500,max_height=500,ratio=1/1',
'b64mimes:jpg,png,webp'
]
]);
$path = signals()->store('avatar', 'avatars', 'public');
auth()->user()->update(['avatar' => $path]);
return hyper()->signals([
'avatarUrl' => Storage::url($path),
'message' => 'Avatar updated successfully!'
]);
}Document Upload
public function uploadDocuments()
{
signals()->validate([
'resume' => [
'required',
'b64file',
'b64max:5120',
'b64mimes:pdf,doc,docx'
],
'cover_letter' => [
'nullable',
'b64file',
'b64max:5120',
'b64mimes:pdf,doc,docx'
]
]);
$paths = signals()->storeMultiple([
'resume' => 'resumes',
'cover_letter' => 'cover-letters'
], 'public');
Application::create([
'user_id' => auth()->id(),
'resume_path' => $paths['resume'],
'cover_letter_path' => $paths['cover_letter'] ?? null
]);
return hyper()->signals([
'message' => 'Application submitted successfully!',
'errors' => []
]);
}Profile Picture with Fallback
public function updateProfile()
{
$rules = [
'name' => 'required|string|max:255',
'bio' => 'nullable|string|max:1000'
];
// Only validate avatar if it's being uploaded
if (signals()->has('avatar') && !empty(signals('avatar'))) {
$rules['avatar'] = 'b64image|b64max:2048|b64mimes:jpg,png';
}
$validated = signals()->validate($rules);
$user = auth()->user();
// Handle avatar upload
if (isset($validated['avatar'])) {
// Delete old avatar
if ($user->avatar) {
Storage::delete($user->avatar);
}
$validated['avatar'] = signals()->store('avatar', 'avatars', 'public');
}
$user->update($validated);
return hyper()->signals([
'message' => 'Profile updated!',
'errors' => []
]);
}Gallery Upload (Multiple Files)
public function uploadGallery()
{
signals()->validate([
'photos' => 'required|array|min:1|max:10',
'photos.*' => [
'b64image',
'b64max:2048',
'b64dimensions:min_width=800,min_height=600',
'b64mimes:jpg,png,webp'
]
]);
$photos = signals('photos');
$paths = [];
foreach ($photos as $index => $photo) {
// Temporarily set the signal for individual storage
$tempSignal = "temp_photo_{$index}";
// Store each photo
$paths[] = signals()->store($tempSignal, 'gallery', 'public');
}
Gallery::create([
'user_id' => auth()->id(),
'photos' => $paths
]);
return hyper()->signals([
'message' => count($paths) . ' photos uploaded!',
'errors' => []
]);
}Technical Details
Base64 Detection
The validation rules automatically detect and handle:
Array format (from Datastar file binding):
json{"avatar": ["/9j/4AAQSkZJRg..."]}Data URL format (with MIME prefix):
json{"avatar": ["data:image/jpeg;base64,/9j/4AAQSkZJRg..."]}Plain base64 string:
json{"avatar": "/9j/4AAQSkZJRg..."}
Performance Considerations
- All validation happens in memory using PHP's native functions
- No temporary files are created during validation
- Image validation uses
getimagesizefromstring()for efficiency - MIME detection uses
finfo_buffer()for non-image files
Size Calculation
Base64 encoding increases file size by ~33%. The validation rules decode the base64 string to validate the actual file size:
// User uploads 1MB image
// Base64 encoded: ~1.33MB
// Validation checks: 1MB (decoded size)
'avatar' => 'b64max:1024' // Validates against original 1MBError Messages
All Hyper validation rules use Laravel's standard validation error messages for consistency:
| Rule | Message Key | Example Message |
|---|---|---|
b64file | validation.file | "The avatar must be a file." |
b64image | validation.image | "The avatar must be an image." |
b64max | validation.max.file | "The avatar must not be greater than 2048 kilobytes." |
b64min | validation.min.file | "The avatar must be at least 100 kilobytes." |
b64size | validation.size.file | "The avatar must be 50 kilobytes." |
b64dimensions | validation.dimensions | "The avatar has invalid image dimensions." |
b64mimes | validation.mimes | "The avatar must be a file of type: jpg, png." |
Related Documentation
- Signals Helper - Signal validation and file storage
- File Uploads - Complete file upload guide
- Validation - General validation patterns
- Blade Directives -
@fileUrlaction

