Laravel Rules Validation two Variables - laravel

I want to validate if a user(member) is part of a group via Validation Rules.
This is a part of my function...
public function update(Request $request)
{
$request->validate([
'idgroup' => [
'required', 'numeric', new AdminGroupRequest
],
'member' => [
'required', 'numeric', new UserPartOfGroup
],
]);
And this is the Rules Class where I want to check if User is part of group.
public function passes($attribute, $value)
{
$userofgroup = Member::where([['groupid', /*Here I need idgroup*/], ['member', $value/*This is already member*/]])->select('id')->first();
if($userofgroup){
return true;
}else{
return false;
}
}
Any ideas?

You could either use the request() helpers:
public function passes($attribute, $value)
{
return Member::where('groupid', request('idgroup'))
->where('member', $value)
->exists();
}
Or you could just use a closure inside your FormRequest:
'member' => [
'required', 'numeric', function ($attribute, $value, $fail) {
$exists = Member::where('groupid', $this->input('idgroup'))
->where('member', $value)
->exists();
if (!$exists) {
return $fail('Your error message goes here.');
}
}
],

Related

How to use validation names and attributes while using custom validator resolver [laravel 6]

I added a custom validation errors using Validator::resolver() as bellow :
class Rest extends Validator
{
public function addFailure($attribute, $rule, $parameters = [])
{
$message = $this->getMessage($attribute, $rule);
$message = $this->makeReplacements($message, $attribute, $rule, $parameters);
$customMessage = new MessageBag();
$customMessage->merge(['code' => strtolower($rule.'_rule_error')]);
$customMessage->merge(['message' => $message]);
$this->messages->add($attribute, $customMessage);
}
}
and i called it using resolver in AppServiceProvider:
Validator::resolver(function($translator, $data, $rules, $messages)
{
return new Rest($translator, $data, $rules, $messages);
});
and while trying to change an attribute name it doesn't work:
$request->validate(
[
'group_id' => 'required'
], [],
[
'group_id' => 'the lesson group'
]);
I usualy extend the validator when the provider is registering
Eg.:
Validator::extend('foo', function ($attribute, $value, $parameters, $validator) {
return $value == 'foo';
});
Remmeber you need to return true or false.
More info: https://laravel.com/docs/6.x/validation#using-extensions

Laravel - How to validate Unique Rule Request as case sensitive

I have this Rules in my Laravel-5.8
Rules: create
public function rules()
{
return [
'location_name' => [
'required',
'string',
'min:3',
'max:80',
Rule::unique('hr_work_locations', 'location_name', 'company_id')
],
];
}
Rules: edit
public function rules()
{
return [
'location_name' => [
'required',
'string',
'min:3',
'max:80',
Rule::unique('hr_work_locations', 'location_name', 'company_id')->ignore($this->work_location)
],
];
}
from the rules,location_name is unique for each company (company_id). Also in the edit rules,
ignore($this->work_location)
is for the route
Controller : create
public function store(StoreWorkLocationRequest $request)
{
try {
$worklocation = HrWorkLocation::create([
'location_name' => $request->location_name,
'is_active' => 1,
]);
Session::flash('success', 'Work Location is created successfully');
return redirect()->route('hr.work_locations.index');
}
catch (Exception $exception)
{
Session::flash('error', 'Action failed!');
return redirect()->route('hr.work_locations.index');
}
}
I observe that it allows location_name as England or england.
How do I make Rule::unique as case sensitive?
Thank you.
Add a custom validation to AppServiceProvider.php under the boot() method:
Validator::extend('iunique', function ($attribute, $value, $parameters, $validator) {
$query = DB::table($parameters[0]);
$column = $query->getGrammar()->wrap($parameters[1]);
return ! $query->whereRaw("lower({$column}) = lower(?)", [$value])->count();
});
This can be extended further to accept the other parameters similar to the unique rule
Now my $rules looks like this:
protected $rules = [
'username' => 'required|alpha_dash|min:5|max:18|iunique:users,username',
];
see an issue reported here
You can make the input lower-cased so you don't have to worry of what the user input in the form.
use Illuminate\Support\Str;
After that, you can call it without the namespace prefix:
Str::lower($request->location_name);

Why laravel validation not work correct when validate for empty string?

Brief:
I have validate request value for empty string.
Code:
if(isset($request->name)) {
$this->validate($request, [
'name' => [
function ($attribute, $value, $fail) {
if (mb_strlen(preg_replace('/\s/', '', $value)) == 0) {
$fail($attribute.' is can't be empty.');
}
}
]
]);
$user->name = $request->name;
$user->save();
}
Also tired with cutom rule.
Rule code:
public function passes($attribute, $value)
{
$result = preg_replace('/\s/', '', $value);
return mb_strlen($result) == 0 ? false : true;
}
/**
* Get the validation error message.
*
* #return string
*/
public function message()
{
return "Attribute value can't be empty string.";
}
Rule testing code:
if(isset($request->name)) {
$this->validate($request, [
'name' => [
new IsEmptyString
]
]);
$user->name= $request->name;
$user->save();
}
Question:
Where I've errors? Why laravel not sending validation error message when I check request value for empty string?
Thanks!
In your situation, you must change your condition to:
if(array_key_exists('name', $request->all())) {
}
When you check isset($request->name) and this condition result return false and the validation code does not even run and for the fact that the conditions returned false.
Generally, your working code looks like this:
if(array_key_exists('name', $request->all())) {
$this->validate($request, [
'name' => [
'required',
function ($attribute, $value, $fail) {
if (mb_strlen(preg_replace('/\s/', '', $value)) == 0) {
$fail($attribute." is can't be empty.");
}
}
]
]);
$user->name = $request->name;
$user->save();
}
Remove the if() condition. and then add the required rule to the validation.
$this->validate($request, [
'name' => ['required',
function ($attribute, $value, $fail) {
if (mb_strlen(preg_replace('/\s/', '', $value)) == 0) {
$fail($attribute.' is can't be empty.');
}
}
]
]);
$user->name = $request->name;
$user->save();

Validation only required when value is not available

I have the following code:
{!! Form::select('the_selection', ['' => 'Nothing', 'Foo' => 'Bar']) !!}
And the following:
<input class="input" name="the_other_field" type="text"/>
The the_other_field field should be required only when the_selection is not '' .
So I tried tis validation:
$this->validate($request, [
// 'recurring' => 'required|nullable',
'the_other_field' => 'required_without:the_selection,|date_format:Y-m-d|after:today',
]);
But that doesnt work..
Use required_if
https://laravel.com/docs/5.6/validation
$this->validate($request, [
// 'recurring' => 'required|nullable',
'the_other_field' => 'required_if:recurring,|required_without:the_selection,|date_format:Y-m-d|after:today',
]);
If this not working you may do this:
$rules = [
'the_other_field' => ['date_format:Y-m-d', 'after:today'],
];
if ($request->get('the_selection') != null) {
array_push($rules['the_other_field'], 'required');
}
$this->validate($request, $rules);
If you move your validation to a form request, then you could add a “sometimes” validation rule:
class YourRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'the_selection' => 'required',
];
}
public function withValidator($validator)
{
$validator->sometimes('the_other_field', 'required', function ($input) {
return $input->the_selection != '';
});
}
}

How to write custom validation rule in controller Laravel?

I have default validation rule in controller Laravel:
$validator = Validator::make($request->all(), [
'email' => 'required|email',
'phone' => 'required|numeric',
'code' => 'required|string|min:3|max:4',
'timezone' => 'required|numeric',
'country' => 'required|integer',
'agreement' => 'accepted'
]);
I tried this, but dont know how to transfer some parameters inside function:
public function boot()
{
Validator::extend('phone_unique', function($attribute, $value, $parameters) {
return substr($value, 0, 3) == '+44';
});
}
How can I extent this validation by my own rule? For example I need to validate concatination of inputs:
$phone = $request->code.' '.$request->phone
After check if $phone are exists in database
I want to use this method:
> $validator->sometimes('phone', 'required|alpha_dash|max:25', function
> ($input) {
> if ((Auth::user()->phone == $input->phone)) {
> return false;
>
> } else {
>
> $t = User::where("phone", $input->phone)->get();
> return ($t->count() > 0) ? false : false;
>
> }
> });
It does not work under all conditions (True, False) inside.
I added new validation nickname_unique:
$validator = Validator::make($request->all(), [
'email' => 'required|email',
'code' => 'required|string|min:3|max:4',
'phone' => 'required|phone_unique',
'timezone' => 'required|numeric',
'country' => 'required|integer',
'nickname' => 'required|alpha_dash|max:25',
'agreement' => 'accepted'
], [
'phone_unique' => 'Phone already exists!',
'nickname_unique' => 'Nickname is busy!',
]);
It does not work, even not call validation rule below previos:
Validator::extend('nickname_unique', function ($attribute, $value, $parameters, $validator) {
dd("Here");
});
You can define your custom validator inside AppServiceProvider like this:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Validator;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
Validator::extend('phone_unique', function ($attribute, $value, $parameters, $validator) {
$inputs = $validator->getData();
$code = $inputs['code'];
$phone = $inputs['phone'];
$concatenated_number = $code . ' ' . $phone;
$except_id = (!empty($parameters)) ? head($parameters) : null;
$query = User::where('phone', $concatenated_number);
if(!empty($except_id)) {
$query->where('id', '<>', $except);
}
return $query->exists();
});
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
//
}
}
You can get all the inputs passed to the validator, by accessing $validator property - getData()
You can just add an extra parameter to your rules array after your custom validation rule (just after the colon) like this:
'phone' => 'required|phone_unique:1',
Pass the id to be ignored while checking entries into the db
The custom validator Closure receives four arguments: the name of the $attribute being validated, the $value of the attribute, an array of $parameters passed to the rule, and the Validator instance.
Now you can call the validator like this:
$validator = Validator::make($request->all(), [
'email' => 'required|email',
'code' => 'required|string|min:3|max:4',
'phone' => 'required|phone_unique:1',
'timezone' => 'required|numeric',
'country' => 'required|integer',
'agreement' => 'accepted'
], [
'phone_unique' => 'Phone already exists!', // <---- pass a message for your custom validator
]);
See more about Custom Validation Rules.
I am writing this answer because I believe bunch of people are looking for some good answer for this topic. So I decided to share my code that I am using for booking site, where I want to check that IS NOT arrival_date > departure_date.
My version of Laravel is 5.3.30
public function postSolitudeStepTwo(Request $request)
{
$rules = [
'arrival_date' => 'required|date',
'departure_date' => 'required|departure_date_check',
'occasional_accompaniment_requested' => 'required|integer',
'accommodation' => 'required|integer',
'are_you_visiting_director' => 'required|integer',
];
if ($request->input('are_you_visiting_director') == 1) {
$rules['time_in_lieu'] = 'required|integer';
}
$messages = [
'departure_date_check' => 'Departure date can\'t be smaller then Arrival date.Please check your dates.'
];
$validation = validator(
$request->toArray(),
$rules,
$messages
);
//If validation fail send back the Input with errors
if($validation->fails()) {
//withInput keep the users info
return redirect()->back()->withInput()->withErrors($validation->messages());
} else {
MySession::setSessionData('arrival_date', $request);
MySession::setSessionData('departure_date', $request);
MySession::setSessionData('occasional_accompaniment_requested', $request);
MySession::setSessionData('accommodation', $request);
MySession::setSessionData('are_you_visiting_director', $request);
MySession::setSessionData('time_in_lieu', $request);
MySession::setSessionData('comment_solitude_step2_1', $request);
//return $request->session()->all();
return redirect("/getSolitudeStepThree");
}
}
My controller is StepController and there I have declared a method as you can see called postSolitudeStepTwo. I declare the rules and on departure date notice that for the rule we have required|departure_date_check. That will be the name of the method in
app/Providers/AppServiceProvider.php
The code there looks like this:
public function boot()
{
Validator::extend('departure_date_check', function ($attribute, $value, $parameters, $validator) {
$inputs = $validator->getData();
$arrivalDate = $inputs['arrival_date'];
$departureDate = $inputs['departure_date'];
$result = true;
if ($arrivalDate > $departureDate) {
$result = false;
}
return $result;
});
}
As the Laravel documentation 5.3 Custom validation rules we need to extend the Validator facade, the signature of that method has to be:
Validator::extend(name_of_the_function, function ($attribute, $value, $parameters, $validator) {
And I believe the rest is clear.
Hope it will help somebody.
$messsages = array(
'email.required'=>'Email is Required',
'phone.required'=>'Phone number is Required',
);
$rules = array(
'email' => 'required',
'phone' => 'required',
);
$validator = Validator::make(Input::all(), $rules,$messsages);
if ($validator->fails()):
$this->throwValidationException($request, $validator);
endif;

Resources