I have a very simple validation that uses a custom rule
<?php
namespace App\Http\Requests\Auth;
use App\Rules\FullWidth;
/**
* @property string $login_id
* @property string $password
*/
class LoginRequest extends \App\Http\Requests\FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'login_id' => [ 'required', 'string', 'min:6', 'max:40', new FullWidth()],
'password' => [ 'required', 'string', 'min:8', 'max:100', new FullWidth()],
];
}
/**
* Get custom attributes for validator errors.
*
* @return array<string, string>
*/
public function attributes(): array
{
return [
'login_id' => 'ログインID',
'password' => 'パスワード',
];
}
}
In the custom Rule I receive the attribute and do the following
<?php
namespace App\Rules;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
class FullWidth implements ValidationRule
{
/**
* Run the validation rule.
*
* @param \Closure(string, ?string=): \Illuminate\Translation\PotentiallyTranslatedString $fail
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
/** @phpstan-ignore argument.type */
if (preg_match('/[^\x01-\x7E\xA1-\xDF]/', $value)) {
$fail($attribute . ' に、全角が含まれています。');
}
}
}
The issue is that, although the function attributes() manages to override all the attributes inside laravel native rules, the custom rule still prints out the initial attribute ("login_idに、全角が含まれています。" instead of "ログインIDに、全角が含まれています。").
I am assuming this is not an intended feature. Although I can probably fix this using the constructor of the custom rule, is there a better way to fix this other than having to pass the attribute value in the constructor every time I use the custom rule?
'login_id' => [ 'required', 'string', 'min:6', 'max:40', new FullWidth("ログインID")],
To ensure that the custom validation rule uses the attribute labels defined in the attributes()
method of the FormRequest
class, you can leverage Laravel's trans()
helper or use __()
for translating the attribute name dynamically.
FullWidth
RuleModify the FullWidth
rule to use Laravel's translation system or a validation attribute resolver. Here's how you can adjust the rule:
Laravel provides access to the Validator
instance where attribute names are already resolved. You can utilize this resolver:
namespace App\Rules;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Support\Facades\Validator;
class FullWidth implements ValidationRule
{
/**
* Run the validation rule.
*
* @param \Closure(string, ?string=): \Illuminate\Translation\PotentiallyTranslatedString $fail
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
/** @phpstan-ignore argument.type */
if (preg_match('/[^\x01-\x7E\xA1-\xDF]/', $value)) {
// Resolve the human-readable attribute name
$validator = Validator::make([], []);
$translatedAttribute = $validator->getTranslator()->get("validation.attributes.$attribute") ?? $attribute;
// Fail with the resolved attribute name
$fail($translatedAttribute . ' に、全角が含まれています。');
}
}
}
If you prefer a simpler approach without accessing the validator, pass the translated attribute when creating the rule instance:
namespace App\Rules;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
class FullWidth implements ValidationRule
{
protected string $attributeName;
public function __construct(string $attributeName)
{
$this->attributeName = $attributeName;
}
/**
* Run the validation rule.
*
* @param \Closure(string, ?string=): \Illuminate\Translation\PotentiallyTranslatedString $fail
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
if (preg_match('/[^\x01-\x7E\xA1-\xDF]/', $value)) {
$fail($this->attributeName . ' に、全角が含まれています。');
}
}
}
Then use the rule in your request:
'login_id' => [ 'required', 'string', 'min:6', 'max:40', new FullWidth(__('ログインID'))],
'password' => [ 'required', 'string', 'min:8', 'max:100', new FullWidth(__('パスワード'))],
trans()
HelperFor a more global solution, dynamically resolve the translated attribute name using Laravel's trans()
or __()
helper. Modify the rule to:
public function validate(string $attribute, mixed $value, Closure $fail): void
{
if (preg_match('/[^\x01-\x7E\xA1-\xDF]/', $value)) {
$translatedAttribute = trans("validation.attributes.$attribute", [], 'ja');
$fail(($translatedAttribute ?: $attribute) . ' に、全角が含まれています。');
}
}
Ensure your lang/ja/validation.php
file contains the attributes
key:
'attributes' => [
'login_id' => 'ログインID',
'password' => 'パスワード',
],
The Option 1 (using the Validator
instance to resolve attributes dynamically) is the most reusable and cleanest solution, as it avoids passing the attribute explicitly in the constructor and works seamlessly with Laravel's translation system.
This method ensures that your rule respects the attributes()
definition in the FormRequest
class without extra manual effort. Let me know if you need further clarification! 🚀
Sign in to participate in this thread!
The Laravel portal for problem solving, knowledge sharing and community building.
The community