webman-tech/laravel-validation
Laravel Validation for Webman lets you use Laravel's familiar Validator, validation rules, error messages, and custom rule objects directly in Webman applications. It adds form and request validation without the full Laravel framework, keeping validation simple and consistent.
The package wires illuminate/validation (Laravel's validator) into Webman, so you get required|email, Rule::in(), unique, exists, sometimes, nested arrays, and the whole rule catalogue without pulling in the Laravel framework.
Install into a Webman app:
composer require webman-tech/laravel-validation
Webman auto-discovers plugins under config/plugin/ — confirm config/plugin/webman-tech/laravel-validation/ was created (or copy it from vendor/webman-tech/laravel-validation/src/config/).
Look first at vendor/webman-tech/laravel-validation/src/ for the facade, the Form base class, and the annotation/attribute handling. The config file governs translation locale, the DB resolver used by unique/exists, and whether annotation scanning is enabled.
First use case — validate a login request in a controller:
use WebmanTech\LaravelValidation\Facades\Validator;
public function login(Request $request)
{
$validator = Validator::make($request->post(), [
'email' => 'required|email',
'password' => 'required|string|min:6',
]);
if ($validator->fails()) {
return json(['code' => 422, 'msg' => $validator->errors()->first()]);
}
// proceed
}
That single call proves the plugin is working end-to-end. Once it does, move rules out of controllers into Form subclasses (see below).
1. Form classes (the day-to-day unit of work). For anything non-trivial, extend the package's base form instead of inlining rules. This mirrors Laravel's FormRequest and keeps controllers thin:
use WebmanTech\LaravelValidation\Form;
class UserStoreForm extends Form
{
public function rules(): array
{
return [
'name' => 'required|string|max:50',
'email' => 'required|email|unique:users,email',
'password' => 'required|min:8|confirmed',
];
}
public function messages(): array
{
return ['email.unique' => '该邮箱已被注册'];
}
public function attributes(): array
{
return ['name' => '用户名'];
}
}
Instantiate with the request payload, call validate, and read errors. This is the pattern you'll repeat across every write endpoint.
2. Scenes / context. For controllers that reuse a form across create and update, define scenes (e.g. create, update) and switch the rule set on the same form class rather than duplicating it. This is the package's answer to Laravel's sometimes-heavy form requests and is the main reason to prefer Form over the facade.
3. Annotation / attribute binding on controller actions. The plugin can attach rules or a form class to an action via an annotation (or PHP 8 attribute, depending on version). This centralises validation at the route boundary and lets a middleware short-circuit before the controller body runs. Use it for uniform endpoints (CRUD-heavy controllers); fall back to explicit $form->validate() when you need conditional logic in the action.
4. Validation middleware. Pair a small middleware that reads the annotation, runs the form, and returns a JSON 422 on failure. This gives you one error envelope across the API, which is worth standardising early.
5. Custom rules. Implement Illuminate\Contracts\Validation\Rule or use closure rules; register global extensions via Validator::extend() in a bootstrap file. Reusable business rules (ID card, phone prefix, tenant-scoped uniqueness) belong here, not in each form.
6. Database-backed rules. unique and exists work off the DB connection the plugin resolves. If you also use webman-tech/laravel-database, it wires up automatically; otherwise confirm the connection resolver is configured, and test one exists rule on day one — this is the most common "works in Laravel, silent-fails here" gap.
7. Error output. Always funnel through one helper: $validator->errors()->toArray() when clients need field-level errors, ->first() for toast-style messages. Add a failedValidation-style hook (or wrap the form call) so you don't sprinkle if ($v->fails()) across every controller.
unique/exists need a wired DB resolver. Without it, these rules throw or silently misbehave. Validate one exists rule before shipping any form that uses it.validation.required, the lang files aren't loaded or the locale isn't set in the plugin config. Set the locale once and keep custom messages in the form's messages().@Validate seems ignored, check that the controller is registered/discoverable and that annotation scanning is enabled in config. Silent no-ops are the classic symptom — verify by intentionally sending invalid payloads.authorize-style method on the form, not in the annotation rule string.Rule::unique() objects inside large foreach blocks.errors() in unit tests. You don't need to boot Webman for validation logic, which keeps the test suite fast.Validator::extend() for global rules, a shared BaseForm for your app's conventions (scenes, authorization, error envelope), and the facade for one-off validations in services or jobs.composer.json, and keep a thin wrapper (your own BaseForm, your own validation middleware) so swapping to another webman validation plugin — or hand-wiring illuminate/validation yourself — stays a contained change rather than a rewrite.How can I help you explore Laravel packages today?