laravel-validation-rules/us-state
Validate US state input in Laravel with ready-made rules for state names, abbreviations, and codes. Catch invalid or misspelled states before they reach your database, keeping addresses and forms clean with simple, reusable validation.
laravel-validation-rules/us-state is a small validation-rule package for US state abbreviations. Release 1.9.0 adds Laravel 12.x compatibility, so use ^1.9 when upgrading or starting on Laravel 12.
Minimal setup:
composer require laravel-validation-rules/us-state
First use case: validating a shipping or billing address form.
use LaravelValidationRules\UsState\UsState;
public function rules(): array
{
return [
'state' => ['required', 'string', new UsState()],
];
}
Start by reading the package rule class and README; there is very little application wiring beyond importing and applying the rule. Test immediately with a valid code such as CA and an invalid code such as ZZ.
StoreAddressRequest / UpdateAddressRequest rather than scattering it across controllers.'state' => ['required', 'string', new UsState()],
'state' => [
Rule::requiredIf($this->input('country') === 'US'),
'nullable',
new UsState(),
],
prepareForValidation() so the rule sees a consistent value.protected function prepareForValidation(): void
{
$this->merge([
'state' => strtoupper(trim((string) $this->input('state'))),
]);
}
Keep the client-side list aligned with the server rule. Populate state selects from your canonical list and still validate server-side; do not rely on the <select> alone.
Pair with other US-address rules where appropriate. If you also validate ZIP codes or country values, compose these rule objects in the same FormRequest for a single validation boundary.
Test at the validation boundary. Cover valid abbreviation, invalid abbreviation, missing value, lowercase input after normalization, and non-US conditional paths.
$this->post('/address', ['state' => 'CA'])->assertSessionHasNoErrors();
$this->post('/address', ['state' => 'XX'])->assertSessionHasErrors('state');
Do not assume a string rule alias exists. Unless your app registers one, use the rule object: new UsState(), not 'us_state'.
Check case sensitivity. Normalize with strtoupper()/trim() before validation rather than assuming the rule accepts lowercase input.
Verify the accepted list for your domain. Confirm whether DC and territories are included if your business rules require them; if not, wrap the package rule or use an explicit Rule::in() list.
Laravel 12 support starts in 1.9.0. If you are upgrading to Laravel 12, update the package and run your address-form tests. The release notes indicate compatibility work, not a breaking API change.
Customize messages at the form layer. If the default validation message is too generic, override it in the FormRequest’s messages() method or wrap the rule if you need fully custom $fail text.
There is little/no config or migration surface. This is a small rule package; the main extension point is wrapping or replacing the rule when your state/territory policy differs from the package’s list.
Debug with the validator directly. When a value unexpectedly fails, test Validator::make(['state' => $value], ['state' => [new UsState()]]) to isolate the rule from request/form behavior.
How can I help you explore Laravel packages today?