I have a form that contains a field for user to enter amount value of certain payment. This field is input of type number.
The validation rule in Laravel for this input is:
'amount' => 'required|numeric'
When I enter the amount in English as: 1500 => The validation passes and everything is OK.
But when I enter the amount in Arabic as: ١٥٠٠ => The validation fails with the following error message:
"validation.numeric"
Should I validate this field manually or is there another solution to this problem?
Maybe you can create your own validation type.
You can add something like this to your boot method in app/Providers/AppServiceProvider.php.
Validator::extend('arabic_numbers', function ($attributes, $value, $parameters, $validation) {
$arabic_numbers = [
'٥',
'١',
// add more
];
$input = $value;
if (!$input) {
return false;
}
$chars = preg_split('//u', $input, -1, PREG_SPLIT_NO_EMPTY);
foreach ($chars as $char) {
if (!in_array($char, $arabic_numbers)) {
return false;
}
}
return true;
});
You can add to your existing rule, e.g. required|arabic_numbers.
Or use something like this:
$input = '١';
$validator = Validator::make([
'user_input' => $input,
], [
'user_input' => 'required|arabic_numbers'
];
if ($validator->fails()) {
//
}
Also you can use in many other ways for example in a custom request:
public function rules()
{
return [
'something' => 'required|arabic_numbers',
];
}
Hope this helps.
Related
I am searching for a improvement to this Laravel FormRequest rule set:
protected $stopOnFirstFailure = true;
public function rules()
{
return [
'reasons' => ['required', 'array'],
'reasons.*.id' => ['exists:reject_reasons,id'],
'reasons.*.text' => Rule::forEach(function ($value, $attribute, $data) {
// get the key from the array attribute
list(, $key) = explode('.', $attribute);
$reason = RejectReason::find($this->reasons[$key]['id']);
return [
Rule::requiredIf(optional($reason)->with_additional_entry),
'max:255'
];
}),
];
}
The .text element should only be required and checked if the id element exists in the database and the attribute with_additional_entry is true.
Things that could be improved:
If the id is not in the database the validator does not stop after the reasons.*.id rule, so I have to check for the $reason Object -> optional()
Get the key of the form array list(, $key) = explode('.', $attribute);
Does anyone have a better solution to this?
I have 3 fields: player1, player2 and winner. I want to validate that winner is equal to either player1 or player 2.
I tried looking for a way to add an 'or' clause to the validation but couldn't find anything, only workarounds for different problems.
You can use a custom validation rule to do this. There's nothing built in that allows comparison to one of many other fields. The closest is the same check, but it only checks against one other field.
(I've added dd() to dump data, you can remove them)
The $values will be what comes from your input.
The $validationRules can be adjusted for your needs.
Validator::extend('equals_one_of', function($attribute, $value, $parameters, \Illuminate\Validation\Validator $validator) {
$fields = $validator->getData(); // all posted values
foreach($parameters as $param) { // this is each of the comma separated fields in the validationRules array
if ($value == $fields[$param]) {
dd("matched");
return true;
}
}
dd("no match");
return false;
});
$values = [
'player1' => 'test1',
'player2' => 'test2',
'winner' => 'test1'
];
$validationRules = [
'player1' => 'required',
'player2' => 'required',
'winner' => 'required|equals_one_of:player1,player2'
];
$validate = Validator::make($values, $validationRules);
// use your validator as normal.
dd($validate->validate());
Actually this rule should be registered with extendDependent to correctly resolve parameter names when used with arrays.
Final code:
class OneOfRule
{
public function validate($attribute, $value, $parameters, $validator) {
if(is_null($value)) return true;
foreach($parameters as $param) {
$other = Arr::get($validator->getData(), $param);
if ($value === $other) {
return true;
}
}
return false;
}
}
public function boot()
{
Validator::extendDependent('one_of', 'App\Http\Validation\Rules\OneOfRule#validate');
}
I have a situation and unfortunately not sure how to sort it out in proper way. I have below script
$validator = Validator::make(
$request->all(),
[
'game_id' => 'required|integer'
],
$messages
);
if ($validator->fails()) {
$response = $validator->messages();
}else{
$response = $gameService->setStatus($request);
}
Now each game has different type, I wanted to add validation on behalf of type. For example if a game is Task Based then I would add validation for time which would be mandatory only for Task based game otherwise it would be an optional for other types.
I have three types of games
1 - level_based
2 - task_based
3 - time_based
In the type table, each game has type.
So is there any way to add validation? I want to do it, inside validation function.
Thank you so much.
You can write your conditions before the validation.
$data = $request->all();
if ($data['game_id'] == 1) {
$rules = [
// level_based validation
];
} else if($data['game_id'] == 2) {
$rules = [
// task_based validation
];
} else {
$rules = [
// time_based validation
];
}
$validator = Validator::make($data, $rules);
Hope it helps. Cheers.
I would go with the required_if validation rule.
So in your case, will send two fields, the type can be a hidden field for example, then on the game_id you will add
'game_id' => 'required_if:type,1'
and so on.. And of course you can customize the error messages.
Try this code snippet
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class CreateGameRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
try {
$request = $this->request->all();
$rule_array = collect();
$rule1 = [
'game_id' => 'required|integer'
]
$rule_array = $rule_array->merge($rule1);
if(isset($request->task_id))
{
$rule2 = [
'task_id' => 'required|integer'
]
}
$rule_array = $rule_array->merge($rule2);
return $rule_array->all();
} catch (Exception $e) {
return $e;
}
}
public function messages(){
return [
'game_id' => 'Please select valid game',
'task_id' => 'Please select valid task'
];
}
}
then invoke this request class in controller function as
use App\Http\Requests\CreateGameRequest;
public function game(CreateGameRequest $request)
{
}
Just trying to do some tags validation. First checking for number of tags (as comma separated list of id's).
class SomePostRequest extends Request
{
public function rules()
{
return [
'tags' => 'between:2,5'
];
}
public function all()
{
$input = parent::all();
$input['tags'] = explode(',', #$input['tags']);
return $input;
}
}
It keeps spititing out the message as
The tags must be between 2 and 5 characters.
Instead of the proper array message:
The :attribute must have between :min and :max items.
Try to use custom validation rule for you requirement:
$this->app['validator']->extend('tag', function ($attribute, $value, $parameters)
{
$tags = explode(',', $value);
if(count($tags) >= 2 || count($tags) <= 5)){
return false;
}
});
and then rules would be
public function rules(){
return [
'tags' => ['tag']
];
}
and message can update by
public function messages() {
return [
'tags.tag' => 'The :attribute must have between :min and :max items.'];
}
I hope, you get basic idea to achieve this requirement, let me know if its helps.
I need to check if a user has posted the same password as the one in the database. Field for old password is 'oldpass'. The custom validator i created is called 'passcheck'. It should fail or pass accordingly.
My UsersController code below doesnt work. What could have I have done wrong?
$rules = array(
'oldpass' => 'passcheck',
);
$messages = array(
'passcheck' => 'Your old password was incorrect',
);
Validator::extend('passcheck', function($attribute, $value, $parameters)
{
if(!DB::table('users')->where('password', Hash::make(Input::get('oldpass')))->first()){
return false;
}
else{
return true;
};
});
$validator = Validator::make($inputs, $rules, $messages);
You should use something like this,
$user = DB::table('users')->where('username', 'someusername')->first();
if (Hash::check(Input::get('oldpass'), $user->password)) {
// The passwords match...
return true;
}
else {
return false;
}
So, you have to get the record using username or any other field and then check the password.
#lucasmichot offered even shorter solution:
Validator::extend('passcheck', function ($attribute, $value, $parameters)
{
return Hash::check($value, Auth::user()->getAuthPassword());
});
I would make it like this:
/**
* Rule is to be defined like this:
*
* 'passcheck:users,password,id,1' - Means password is taken from users table, user is searched by field id equal to 1
*/
Validator::extend('passcheck', function ($attribute, $value, $parameters) {
$user = DB::table($parameters[0])->where($parameters[2], $parameters[3])->first([$parameters[1]]);
if (Hash::check($value, $user->{$parameters[1]})) {
return true;
} else {
return false;
}
});
This validator rule will make database query to check current user's password
You can make it even shorter and save query:
Validator::extend('passcheck', function ($attribute, $value, $parameters) {
return Hash::check($value, Auth::user()->getAuthPassword());
});
Please dont tie your rule to an Html element. Use the parameters Laravel provides to create your custom rules. This would be (asuming that you have a user authenticated):
Validator::extend('passcheck', function($attribute, $value, $parameters) {
return Hash::check($value, Auth::user()->password); // Works for any form!
});
$messages = array(
'passcheck' => 'Your old password was incorrect',
);
$validator = Validator::make(Input::all(), [
'oldpass' => 'passcheck',
// more rules ...
], $messages);