Laravel validating something else after form-request validation - laravel

How can I validate something else after the regular validation in a form-request?
I need to verify that a folder does exists or not based on the name given in a input.
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class CreateFolder extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return (auth()->check() && auth()->user()->can('create folders'));
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'name' => 'required|between:1,64|string'
];
}
}
I want to use the same name when I validate that the folder exists or not after the regular validation. The docs didn't specify anything useful as I could see.

You can use custom rule as a closure, so other rules will be same.
return [
'name' => ['required','between:1,64','string',function ($attribute, $value, $fail) {
if (file_exists(public_path('files/').$value)) {
$fail(':attribute directory already exists !');
}
}]
]
I hope you understand.

Laravel has a mechanism to write a custom rule for validation. Please have a look at https://laravel.com/docs/5.8/validation#custom-validation-rules
Furthermore, I would suggest using a Storage object to check whether a file exists or not will be a more convenient and robust solution. One can refer to the official documentation at https://laravel.com/docs/5.5/filesystem#retrieving-files
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class CreateFolder extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return (auth()->check() && auth()->user()->can('create folders'));
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'name' => ['required',
'between:1,64',
'string',
function ($attribute, $value, $fail) {
if (!Storage::disk('local')->exists('file.jpg')) {
$fail($attribute.' does not exist.');
}
},
];
]
}
}

Related

Laravel: how to call custom Validator inside the rules() function of a custom FormRequest class?

Looking at the documentation https://laravel.com/docs/9.x/validation I kinda understand how you can make a custom Validator and call it as an object within a controller function.
I am familiar with using custom FormRequests, but it's not clear to me how to call a custom Validation within the rules() function of a custom FormRequest class instead.
For example if I want to use the following example from the documentation:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
 
Validator::make($data, [
'zones' => [
'required',
Rule::in(['first-zone', 'second-zone']),
],
]);
Where do I have to define the above and how can I then get to the point where I can call it like this:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class TestRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array<string, mixed>
*/
public function rules()
{
return [
'zone' => 'zones', // Using the custom Validator
];
}
}
There is this example that sort of explains a little bit Laravel - Use validation rule inside Custom Validation but it doesn't actually say how to then use it withing the rules() function
There is also documentation on how to create a custom Rule (which I'm supposing is a required step unless the custom role can be defined within the FormRequest).
<?php
 
namespace App\Rules;
 
use Illuminate\Contracts\Validation\InvokableRule;
 
class Uppercase implements InvokableRule
{
/**
* Run the validation rule.
*
* #param string $attribute
* #param mixed $value
* #param \Closure $fail
* #return void
*/
public function __invoke($attribute, $value, $fail)
{
if (strtoupper($value) !== $value) {
$fail('The :attribute must be uppercase.');
}
}
}
But the only example available on how to call it is as a validation object, not as a rule inside a FormRequest (unless I misunderstand), so that isn't helpful for my intentions.
use App\Rules\Uppercase;
 
$request->validate([
'name' => ['required', 'string', new Uppercase],
]);
You already found the way how to use the your custom validator in your FormRequest. At method rules, just use it like 'New Uppercase' in array. So the example will be like below (* I add example zone is required and Uppercase):
public function rules()
{
return [
'zone' => ['required', new Uppercase]
];
}
Dont forget to import your custom validator class.

How to validate images array type using rule object with custom message in Laravel

Actually, I tried to create rule object which is able to validate every image type in array of images and not only enough but also, I must to show custom message in override message function in rule object.
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class ImagesArray implements Rule
{
/**
* Create a new rule instance.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Determine if the validation rule passes.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
public function passes($attribute, $value)
{
return [$attribute => 'mimes:jpeg,jpg,png' ];
here i need to validate these file types.
}
/**
* Get the validation error message.
*
* #return string
*/
public function message()
{
return 'The validation error message.';
here, I need to show my custom messgae.
}
}
You should use Request.
For example, create q request class: php artisan make:request MyRequest.
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class MyRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'image' => 'mimes:jpeg,jpg,png',
];
}
public function messages()
{
return [
'image.mimes' => 'This image is not supported.',
];
}
}
In your controller import class MyRequest and in the method use MyRequest
e.g:
public function store(MyRequest $request)
{ // your code
}
Let me know if that was helpful. Thanks!
When validating arrays or nested parameters, you should use . in your rules access a specific array index. but if you want to apply a rule to every index on that array, you can use .*.
$validator = Validator::make($request->all(), [
'image.*' => 'mimes:jpeg,jpg,png',
], [
'image.*' => 'Invalid file type.',
]);
Or if you're using Request Forms
public function rules(){
return [
'image.*' => 'mimes:jpeg,jpg,png',
];
}
public function mesages(){
return [
'image.*' => 'Invalid file type.',
];
}
For more info, see Laravel's Documentation on Validation Arrays

Laravel unique field validation

I have a Product model with a text input field for the product number. In my Laravel application I validate this field to be unique to that specific user. So two users can have a same product number, but one user cannot have duplicate. So far the validation rules work when adding new products:
'product_no' => 'nullable|unique:products,product_no,NULL,id,user_id,' . auth()->user()->id
However, when editing the same product, the validation fails. Probably because it already exists. I am not sure how to exclude the existing ID in the validation. Any ideas?
Example as requested
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class Request1 extends FormRequest
{
private $rules;
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
public function __construct()
{
parent::__construct();
$this->rules = [
'password' => [
'nullable',
]
];
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return $this->rules;
}
}
And the one with unique looks like this then
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class Request2 extends Request1
{
public function __construct()
{
parent::__construct();
$this->rules[] = 'unique:products,product_no,NULL,id,user_id,' . auth()->user()->id';
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return $this->rules;
}
}

FormRequest errors returns array with wrong array keys

First time i run into this problem, never had it before. I've got the following FormRequest class:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ValidateForm extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'name' => 'required',
];
}
}
When validation fails, after redirect the $errors object returns the following:
Array
(
[0] => The name field is required.
)
The array key is numeric, so i can't use $errors->has('name') , does anyone know what is causing this behaviour?

Laravel validation required_if with in:1

I need to use required_id with a in:1 as this field is required to be checked only if another field equal to 4
'affirm_agency' => 'required_if:role,4|in:1',
but when I write it that way I can't pass the validation when it doesn't equal to 1
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class userRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return false;
}
public function rules()
{
return [ 'affirm_agency' => 'required_if:role,4|in:1',];
}
}
I typically handle something like this like so:
/**
* Validation rules
*
* #return array
*/
public function rules() : array
{
$rules = [
// add whatever default rules you always want
];
if (request()->role == 4) {
$rules['affirm_agency'] = 'required|in:1';
}
return $rules;
}
Please see laravel documentation
in:foo,bar,...
The field under validation must be included in the given list of values. Since this rule often requires you to implode an array, the Rule::in method may be used to fluently construct the rule:
use Illuminate\Validation\Rule;
Validator::make($data, [
'zones' => [
'required',
Rule::in(['first-zone', 'second-zone']),
],
]);
You need to update you authorize function as it is returning false now.
public function authorize()
{
return true;
}

Resources