phpviet/validation
Laravel validation rules for Vietnamese-specific data such as phone numbers, citizen ID cards, tax codes, and other local identifiers, with ready-to-use rules and localized error messages.
composer require phpviet/validationconfig/app.php manually. There is usually nothing to configure to get started.php artisan vendor:publish --provider="PhpViet\Validation\ValidationServiceProvider"
src/ — one class per rule; read the class if the README is ambiguous.CHANGELOG.md — the 1.0.2 release note is just a link to it, so read the actual entry before upgrading.$request->validate([
'phone' => ['required', 'string', 'vietnamese_phone'],
'identity_card' => ['nullable', 'string', 'vietnamese_identity_card'],
]);
Confirm the exact rule strings against your installed version's README; aliases are the most common source of "rule not found" confusion.Prefer FormRequests over inline validation. The rules are verbose in controllers and you will reuse them across register/profile/admin-edit flows.
class StoreUserRequest extends FormRequest
{
public function rules(): array
{
return [
'phone' => ['required', 'string', 'bail', 'vietnamese_phone', 'unique:users,phone'],
'identity_card' => ['nullable', 'string', 'vietnamese_identity_card', 'unique:users,identity_card'],
];
}
}
Normalize input before validating, not after. Users paste +84 912 345 678, 0912.345.678, or numbers with non-breaking spaces. Strip separators in prepareForValidation() so both the rule and your unique check see the same canonical value:
protected function prepareForValidation(): void
{
$this->merge([
'phone' => preg_replace('/[\s.\-()]/', '', (string) $this->phone),
]);
}
Use rule objects for conditional/business logic. String aliases are fine for simple fields; instantiate the rule class when you need constructor arguments (e.g. restricting to mobile-only, or a specific carrier prefix) or when you want the rule unit-testable in isolation.
Pair with sometimes / nullable deliberately. A partial-update endpoint should use sometimes|..., otherwise an absent key fails validation and forces clients to resend the whole record.
Localize the messages. If the package ships vi translations, publish them and confirm the :attribute placeholder renders your field label rather than the raw column name — set attributes() in the FormRequest.
Test with data providers. Validation rules are pure functions of a string, which makes them ideal for table-driven tests:
public static function phones(): array
{
return [
['0912345678', true],
['+84912345678', false], // if the rule expects local format
['0912', false],
['', false],
];
}
This is also the fastest way to pin down behaviour after a patch release like 1.0.2 — you get a regression suite that tells you immediately whether the regex tightened or loosened.
Reuse on the API and Blade side. Expose the same rule set through a shared RuleSet/rules() trait so web forms, API resources, and import jobs cannot drift apart. Import jobs especially benefit: run each row through Validator::make() with the same rules rather than hand-rolling checks.
+84 vs 0 prefixes and from landline-vs-mobile distinctions. Decide once which canonical form you store, document it, and normalize at the boundary. If the rule only accepts one form, +84 input will fail silently in the sense that it returns a generic "invalid" message.null. Laravel's ConvertEmptyStringsToNull middleware turns "" into null, so nullable works — but only for HTTP requests. Console commands, queue payloads, and Validator::make() calls bypass the middleware and will pass "" straight through. Use filled or normalize explicitly in those paths.bail placement. Put bail first so a malformed number doesn't also trigger a unique database query. Cheap wins on high-traffic registration endpoints.vendor/ is lost on the next composer update. If there is no publish tag, override the message with the third argument to validate() or a messages() method on the FormRequest instead.CHANGELOG.md, which is not surfaced in Composer's output. Before bumping, read the changelog entry and run your data-provider tests; a "fix" to a phone regex can silently reject numbers you already have in production."phpviet/validation": "^1.0" is safe for patch updates, but if your stored data depends on acceptance behaviour, add the validation test suite to CI so a minor bump that tightens a rule fails the build rather than rejecting real users.Validator::extend), the last registration wins. Check Validator::getRules() in Tinker if a rule behaves unexpectedly.dd() the rule class's regex against your input directly, and check that the value isn't an array or object (form-array input from a misconfigured name="phone[]" will fail every string rule).+84), wrap it rather than fork it — a small custom rule that normalizes and then delegates keeps you on the package's future bug fixes while adding your own leniency.How can I help you explore Laravel packages today?