how to call laravel validation rules in a closure function in laravel? - php

I wish to skip the captcha validation if the account,which maybe a email or mobile, has been captcha validated.
so I write a colsure function. if the session('captcha_validated_reset_account') equals to the account which user input, it will skip the captcha validation.
if not, the program will call a laravel validation rule like "required|captcha"(captcha' comes from https://github.com/mewebstudio/captcha).
The problem is I don't know how to call validation rule in a closure,I tried return 'required|captcha' but it not work as intended.
'captcha' => function($attribute, $val, $fail) use ($request) {
if (
! empty(session('captcha_validated_reset_account'))
&& session('captcha_validated_reset_account') == $request->input('account')
) {
return;
} else {
Rule::required... //and call a rule named 'captcha' to validate the captcha code from user input
//return 'required|captcha';
}
}
Is any way I can call laravel validation rules in a closure function?

You should put the closure in an array:
'captcha' => [ function ($attribute, $val, $fail) use ($request) {
if (
empty(session('captcha_validated_reset_account'))
&& session('captcha_validated_reset_account') != $request->input('account')
) {
$fail($attribute . ' is required.');
}
}]
Note that I've changed the condition.

Related

Livewire extended validation with dynamic replaced message

Adding a custom video length validaiton rule but the :max_duration is never replaced in the error message addReplacer method is never called. Is there a livewire way of doing this?
Validator::extend('video_length', function ($attribute, $value, $parameters, $validator) {
$max_seconds = $parameters[0];
// Replace dynamic variable
$validator->addReplacer('video_length_duration', function ($message, $attribute, $rule, $parameters) use ($max_seconds) {
return trim(str_replace(':max_duration', gmdate("H:i:s", $max_seconds), $message));
});
return false;
}, 'Video duration must be less then :max_duration');
$this->validate([
'file' => 'required|file|max:102400|video_length:86400',
]);

Laravel Middleware Too few arguments to function error

I am trying to setup a middleware to check if inputs are empty on form submit for updating a users settings, and if so to return them back to the same page with an error. When I set it up, it gives me the error
Too few arguments to function App\Http\Middleware\AdminUserUpdate::handle(), 2 passed in /var/www/market/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php on line 167 and exactly 3 expected
It seems to be the id I pass through, here is the rest of my code
Middleware:
public function handle(Request $request, Closure $next, $id)
{
if($request->input('username') == NULL) {
return redirect()->route('admin.members.view', $id)->with('error', 'You must enter a username for this user in order to update their account!');
} elseif($request->input('email') == NULL) {
return redirect()->route('admin.members.view', $id)->with('error', 'You must enter a email for this user in order to update their account!');
} elseif($request->input('admin') == NULL) {
return redirect()->route('admin.members.view', $id)->with('error', 'You must select whether this user is a root admin or not in order to update their account!');
} elseif($request->input('banned') == NULL) {
return redirect()->route('admin.members.view', $id)->with('error', 'You must select whether this user is banned or not in order to update their account!');
} elseif($request->input('role') == NULL) {
return redirect()->route('admin.members.view', $id)->with('error', 'You must select a role for this user in order to update their account!');
}
return $next($request);
}
Kernel:
'AdminUserUpdate' => \App\Http\Middleware\AdminUserUpdate::class,
Route:
Route::middleware(['AdminUserUpdate'])->group(function () {
Route::post('/app/members/{id}/submit', 'App\Http\Controllers\Admin\Members\IndexController#Submit')->name('admin.members.submit');
});
I have the ID passed through so I can return them back to the view page for the specific users id, but it doesnt seem to like that for some reason. Anyone have any thoughts?
Middlewares doesn't read route parameters. Use colon to pass a parameter to the middleware.
Route::middleware(['AdminUserUpdate:123'])->group(function () {
Link to Middleware Parameters docs
I suggest to change the way you validate your fields.
In your case, this command create the form validator file
php artisan make:request UpdateUserRequest
In the file UpdateUserRequest.php
This block have all the rules you want to validate
public function rules()
{
return [
'username' => 'required',
'email' => 'required',
... other fields for validation ...
];
}
and inside the store method in your Controller, only this line is required to manipulate all the data after the validation:
$validated = $request->validated();
and for custom messages, add this into your UpdateUserRequest:
public function messages()
{
return [
'username.required' => 'You must enter a username for this user in order to update their account!',
'email.required' => 'You must enter a email for this user in order to update their account!',
... and other validation messages ...
];
}
For more details and ways to validate your forms, check the link:
Form Request Validation

Laravel append rules on custom validation rule

In request I got attribute that defines validation rules and flow. Let's say it is account_type: business, personal.
Each value changes validation flow and requires different attributes to be present ir request.
Let's say I have following custom rules methods:
public function validateAccountTypeBusiness($attribute, $value, $parameters, Validator $validator)
{
// check is present:
// Company address
// VAT number
}
public function validateAccountTypePersonal($attribute, $value, $parameters, Validator $validator)
{
// check is present:
// User mobile phone
}
Since each rule requires more than single attribute to be presented in this request depending on account type ( vat number, company name, etc ) returning false would be not informative to user because generated response notices that account type is invalid without any details which actual attributes is missing.
The question is: how I can append more rules to be validated in this validation custom rule?
Following not working:
public function validateAccountTypeBusiness($attribute, $value, $parameters, Validator $validator)
{
$validator->addRules([
'company_address' => 'required|string',
'vat_number' => 'required',
]);
}
If you follow Complex Conditional Validation, you can validate using the following way
Step 1: Create Validator instance with static rules which would be same in both the cases(business or personal account) like name,check,phone,email,etc.
$v = Validator::make($data, [
'email' => 'required|email',
'name' => 'required|alpha',
'phone' => 'required|numeric',
'check' => 'required' //common in both account type
//add more rules as required
]);
Step 2: Add specific rules with condition
$v->sometimes('VAT', 'required|max:50', function ($input) {
return $input->account_type == 'business';
});
$v->sometimes('Company_address', 'required|max:500|alpha', function ($input) {
return $input->account_type == 'business';
});
$v->sometimes('user_mobile', 'required|numeric', function ($input) {
return $input->account_type == 'personal';
});
Parameters for sometimes() method :
The first argument passed to the sometimes method is the name of the
field we are conditionally validating. The second argument is the
rules we want to add. If the Closure passed as the third argument
returns true, the rules will be added.
As per my understanding, Custom validation rule can be used for only one parameter & you're trying to club them together.
This is one of many ways to approach your problem. Hope it helps.
<?php
namespace App\Http\Controllers;
use Validator;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class AccountController extends Controller
{
/**
* Store a new user account.
*
* #param Request $request
* #return Response
*/
public function store(Request $request)
{
if($request->input('account_type' == 'business') {
// Validation for business account
$validator = Validator::make($request->all(), [
'company_address' => 'required|string',
'vat_number' => 'required',
]);
}
else {
// Validation for personal account
$validator = Validator::make($request->all(), [
'contact_number' => 'required',
]);
}
if ($validator->fails()) {
return redirect('account/create')
->withErrors($validator)
->withInput();
}
// Store the user account...
}
}
Reference -
Manually creating validators -
https://laravel.com/docs/5.4/validation#manually-creating-validators

How to create custom validation within the same controller?

I have a form which performs the inserting function, the related method is :
public function addthread(Request $request) {
//validate
$this->validate($request, [
'title' => 'required|unique:thread|max:255',
'num_opt' => $this->checkOpt($request),
]);
}
I want to use a custom function to validate the num_opt elements,:
protected function checkOpt($request, Validator $validator) {
//$num_opt = $request->input('num_opt');
if ($request->has('$num_opt')) {
//$validator->errors()->add ??
How to customize the error message?
}
//die();
}
Questions:
Is the above code practice is wrong or not?
How can I access $validator and customize the error message in the checkOpt function?

Laravel 4 validator for password field in edit account

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);

Categories