Laravel use Hash as Validator - php

i'm using Hash::check() to check current password with entered password. i use this if for check this action
$HashPassowrd = Hash::make(Input::get('password'));
if( ! Hash::check( Input::get('currPassword') , $data->password ) )
{
return Redirect::to('profile.update')
->withErrors('Current Password in Incorrect!');
}
how to use that as validator ? for example in this rules
$rules = array(
'name' => 'required|alpha',
'family' => 'required',
'email' => 'required|email',
'currPassword'=> 'required',
'password' => 'required|confirmed',
'password_confirmation'=>'required',
);

You can add custom rule in to the validator:
Validator::extend('checkHashedPass', function($attribute, $value, $parameters)
{
if( ! Hash::check( $value , $parameters[0] ) )
{
return false;
}
return true;
});
Now you can use this custom rule as:
'currPassword' => 'required|checkHashedPass:' . Input::get('currPassword')
So, if the validation fails for this rule then you'll get error messages for this in your view and can access using $errors->first('currPassword'); but you need to pass a custom error message for this custom rule you've created using:
$messages = array( 'currPassword.checkHashedPass' => 'Current Password failed!' );
So, during validation you have to pass the $messages array using:
$validator = Validator::make(Input::all(), $rules, $messages);
Check custom validation rules on the documentation.

You also can use a closure validation rule:
[
'currPassword' => function ($attribute, $value, $fail) {
if (! Hash::check($value, $this->user()->password)) {
$fail('Your current password doesnt match');
}
},
'password' => 'required|min:6|confirmed',
];

Since Laravel 6.x a password validation rule is added that will do the above for you.
Check its documentation
simply add this rule to your validation rules :
'password' => 'password:api'
where api is the authentication guard

Related

Concaternate Array value with Ternary Operator result

I'm using PHP 7 and Laravel 6. I got errors when I made a user request rule and used it in user controller. The request rule I made is to be reusable in create and update function, so if i pass the id of user, it will validate the unique of user except that id. But if not, it will search all the ids and validate if it's unique. I follow BaM solution, here: https://stackoverflow.com/a/24205849
This my UserRequest.php:
public static function rules ($id=0, $merge=[]) {
return array_merge(
[
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users' . ($id ? ",$id" : ''),
'phone_number' => 'required|string|min:9|max:10|unique:users' . ($id ? ",$id" : ''),
'user_img' => 'required|mimes:jpeg,jpg,png,gif|max:10000',
],
$merge);
}
This is my UserController:
public function store(Request $request)
{
$extend_rules = [
'pass' => 'required|string|min:8',
];
$validator = Validator::make($request->all(), UserRequest::rules($extend_rules));
if ($validator->fails())
{
return redirect()->back();
}
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->pass),
'phone_number' => $request->phone_number,
'user_img' => $request->user_image->store('user_img'),
]);
$user->save();
Session::flash('message', 'Your account is successfully created !');
Session::flash('alert-class', 'alert alert-success');
return redirect()->route('users.index');
}
And I got this errors:
ErrorException: Array to string conversion
I tried to search for solutions but couldn't seem to find anything much my case.
If anyone know, please help me!
That's because you're just passing an array while the method accept two different type of parameter
$validator = Validator::make($request->all(), UserRequest::rules(0, $extend_rules)); // <-- you need to either pass 1 or 0 for the id and then $extended rules
// here is your method signature
public static function rules ($id=0, $merge=[]) {

Return error response if a body params is not mentionned in the validator

I'm using the Laravel Validator to test my incoming request. So to be sure that the request contains an username and an email, I write something like that:
$validator = Validator::make($request->all(), [
'username' => 'required',
'email' => 'required|email'
]);
if ($validator->fails()) {
return response()->json('error', 400);
};
But if in my request I have an additionnal params like name, the validator will not consider it as an error and will not fail.
Have you an idea how I can make my validator more strict so that the request body match exactly?
Technically it's not a validation fail in the Validator. But you could check if there are extra (unexpected) fields and send a JSON response based on that if you wanted.
Something like this maybe?
$validationRules = [
'username' => 'required',
'email' => 'required|email'
];
$validator = Validator::make($request->all(), $validationRules);
// Check if there are extra (unexpected) fields and fail in that case
$extraFields = $request->except(array_keys($validationRules));
if (count($extraFields) > 0) {
return response()->json('error because there are extra fields', 400);
}
if ($validator->fails()) {
return response()->json('error', 400);
}
return response()->json('ok', 200);
I hope it can help you.
Validation rules can be attached only to properties, so I don't think Laravel's Validator is able to do that. But you still can explicitly forbid certain fields by providing a custom closure rule to them, like this:
$denied = function($attr, $value, $fail) {
$fail("{$attr} is denied.");
};
$validator = Validator::make($request->all(), [
'username' => 'required',
'email' => 'required|email',
'name' => $denied,
'password' => $denied
]);
Otherwise you need to implement custom validation logic, probably utilizing the rule array from your validator as a white list.

Validate a field: required_if the url contains parameter in Laravel

Is there any way to validate required field when the requested url contains some parameter?
Assuming you are using Form requsts, you can simple use PHP condition.
public function rules()
{
$rules = []; // here you put some rules
// here you check condition and add some rule when it's true
if (str_contains($this->input('url'), 'something')) {
$rules['some_other_field'] = 'required';
}
return $rules;
}
You need to first check the route before validating....
$roles =[
'title' => 'required|unique:posts|max:255',
'author.name' => 'required',
'author.description' => 'required',
];
if(Route::getCurrentRoute()->getPath() == "xxxxx"){
$role['desc'] = 'required'
}
if(\Request::route()->getName() == "yyyy"){
$role['desc'] = 'required'
}
if($request->is('admin/*')){
$role['desc'] = 'required'
}
$this->validate($request, $role);

Laravel custom validation rule

How can i make a custom validation rule to an input which value must be an integer and starting with 120?
I already read about making custom messages but didnt understand about rules.
I want to use a regex to validate the data. ^120\d{11}$ here is my regex.
I'm new in Laravel that's why cant now imagine how to do that.
A custom validation to use it in $this->validate($request, []);
Now i'm validating data like so:
$this->validate($request, [
'user_id' => 'integer|required',
'buy_date' => 'date',
'guarantee' => 'required|unique:client_devices|number',
'sn_imei' => 'required|unique:client_devices',
'type_id' => 'integer|required',
'brand_id' => 'integer|required',
'model' => 'required'
]);
The input that i want to add custom validation is guarantee
The quickest neatest way is an inline validator in your controller action:
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'number' => [
'regex' => '/^120\d{11}$/'
],
]);
if ($validator->fails()) {
return redirect('post/create')
->withErrors($validator)
->withInput();
}
return view('welcome');
}
Where number is the name of the field being submitted in the request.
If you have a lot of validation to do, you might want to consider using a Form Request instead, as a way of consolidating a lot of validation logic.
You can create custom validations in your controller as:
$name = Input::get('field-name')
$infoValidation = Validator::make(
array( // Input array
'name' => $name,
),
array( // rules array
'name' => array("regex:/^120\d{11}$"),
),
array( // Custom messages array
'name.regex' => 'Your message here',
)
); // End of validation
$error = array();
if ($infoValidation->fails())
{
$errors = $infoValidation->errors()->toArray();
if(count($errors) > 0)
{
if(isset($errors['name'])){
$response['errCode'] = 1;
$response['errMsg'] = $errors['name'][0];
}
}
return response()->json(['errMsg'=>$response['errMsg'],'errCode'=>$response['errCode']]);
}
Hope this helps.
Since Laravel 5.5, you can make the validation directly on the request object.
public function store(Request $request)
{
$request->validate([
'guarantee' => 'regex:/^120\d{11}$/'
]);
}

Laravel validation OR

I have some validation that requires a url or a route to be there but not both.
$this->validate($request, [
'name' => 'required|max:255',
'url' => 'required_without_all:route|url',
'route' => 'required_without_all:url|route',
'parent_items'=> 'sometimes|required|integer'
]);
I have tried using required_without and required_without_all however they both get past the validation and I am not sure why.
route is a rule in the route field
I think you are looking for required_if:
The field under validation must be present if the anotherfield field is equal to any value.
So, the validation rule would be:
$this->validate($request, [
'name' => 'required|max:255',
'url' => 'required_if:route,""',
'route' => 'required_if:url,""',
'parent_items'=> 'sometimes|required|integer'
]);
I think the easiest way would be creation your own validation rule. It could looks like.
Validator::extend('empty_if', function($attribute, $value, $parameters, Illuminate\Validation\Validator $validator) {
$fields = $validator->getData(); //data passed to your validator
foreach($parameters as $param) {
$excludeValue = array_get($fields, $param, false);
if($excludeValue) { //if exclude value is present validation not passed
return false;
}
}
return true;
});
And use it
$this->validate($request, [
'name' => 'required|max:255',
'url' => 'empty_if:route|url',
'route' => 'empty_if:url|route',
'parent_items'=> 'sometimes|required|integer'
]);
P.S. Don't forget to register this in your provider.
Edit
Add custom message
1) Add message
2) Add replacer
Validator::replacer('empty_if', function($message, $attribute, $rule, $parameters){
$replace = [$attribute, $parameters[0]];
//message is: The field :attribute cannot be filled if :other is also filled
return str_replace([':attribute', ':other'], $replace, $message);
});

Categories