Validation & Sessions
The Validateable trait adds a fluent validation DSL to any action, while native PHP sessions are wrapped in small static facades for storage and flash messages.
Validation
Use vfield($key, $value) and chain rules; each rule registers a first-wins error message.
<?php
namespace App\Actions;
use System\Http\Action;
use System\Http\Traits\Validateable;
class RegisterAction extends Action {
use Validateable;
public function middlewares() { return []; }
public function main() {
$this->vfield("email", $this->input("email"))->required()->email();
$this->vfield("password", $this->input("password"))->required()->min_length(8);
if (!$this->validated()) {
return response()->status(422)->json(["errors" => $this->errors()]);
}
return response()->json(["ok" => true]);
}
}
Available rules
| Rule | Example | Description |
|---|---|---|
file() | ->file() | Value must be a valid upload (isfile(): UPLOAD_ERR_OK + is_uploaded_file). |
mimes([...]) | ->mimes(["image/png", "image/jpeg"]) | File MIME must be in the list (sniffed with finfo). |
max_size(MB) | ->max_size(2) | Upload size limit in megabytes (chainable). |
required() | ->required() | Value must be set and non-empty (after trim). |
email() | ->email() | Valid email via FILTER_VALIDATE_EMAIL. |
min_length(n) | ->min_length(8) | String length must be ≥ n. |
max_length(n) | ->max_length(100) | String length must be ≤ n. |
equals($x) | ->equals($confirm) | Strict equality with another value. |
custom($cb, $msg) | ->custom(fn($v) => in_array($v, ["a","b"])) | User callback must return truthy. |
Trait methods
| Method | Description |
|---|---|
error($key, $message) | Register an error (first-wins per key). |
validated() | Runs an optional validate() method if defined, then returns empty($errors). |
errors() | Returns the error map [key => message]. |
required(),email(),min_length()andmax_length()assume scalar input — they crash with aTypeErroron array input (e.g.email[]=). Validate files withfile()/mimes()and treat arrays as invalid before these rules.required()uses PHP’sempty()internally, so"0"/0/""count as missing.file()requires a real HTTP upload, so it fails under CLI/tests.
Sessions
Sessions use native PHP sessions, started in public/index.php with
hardened cookie parameters (httponly on, samesite=Lax, and
secure when the request is HTTPS) before session_start().
use System\Support\Session;
Session::put("user_id", 42);
Session::get("user_id"); // 42
Session::has("user_id"); // true
Session::delete("user_id");
Session::get() returns false (not null) when a key is missing or empty.
Flash messages
Flash messages are JSON-encoded into the session and consumed on read:
use System\Support\Flash;
Flash::success(["Account created!"]);
Flash::error(["Invalid password"]);
Flash::warning(["Disk almost full"]);
Flash::info(["New version available"]);
Render them in a view — @message is replaced once per item, then the flash is cleared:
<?php
Flash::render("success", '<div class="alert alert-success">@message</div>');
Flash::render("error", '<div class="alert alert-danger">@message</div>');
?>
render($type, $html, $escape = true) escapes each message with htmlspecialchars by default — pass false as the third argument only when the message is trustworthy raw HTML.
Raw flashes
Flash::set("just_saved", true);
Flash::get("just_saved"); // true (consumed on read)
Flash in a redirect cycle
public function main() {
$this->vfield("name", $this->input("name"))->required()->min_length(2);
if (!$this->validated()) {
Flash::error($this->errors());
return response()->redirect(route("products.index"));
}
Flash::success(["Product created!"]);
return response()->redirect(route("products.index"));
}
Part of the Lunaris documentation · Source on Codeberg · MIT License