Validating an array based on value - php

I'm passing an object to my Laravel application which contains either a url or alpha numeric input based on another parameter provided. I can't figure out how to validate the value based on the other parameter. E.g.
feeds: [
0: {source: "https://www.motorsport.com/rss/all/news/", type: "user", error: false}
1: {source: "abc-news", type: "newsapi", error: false}
2: {source: "the-verge", type: "newsapi", error: false}
]
So in this case, if the type is user, I need to validate the URL, but if it's newsapi then I need to validate with a regex.
I'm using the rules in Requests to handle this along with the error messages to be returned. Here's the rules, obviously the last 2 representing what I'm trying to do, but without the logic of checking the type.
return [
'name' => 'required|min:1|regex:/^[A-Za-z0-9_~\-!##\$%\^&\(\)\s]+$/',
'feeds.*.source' => 'url',
'feeds.*.source' => 'min:1|regex:/^[A-Za-z0-9\-]+$/',
];
Answer:
Thanks #Ali for the answer, with that info I was able to find this post: How to use sometimes rule in Laravel 5 request class and change my Request to:
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'name' => 'required|min:1|regex:/^[A-Za-z0-9_~\-!##\$%\^&\(\)\s]+$/'
];
}
/**
* Configure the validator instance.
*
* #param \Illuminate\Validation\Validator $validator
* #return void
*/
public function withValidator($validator)
{
$validator->sometimes('feeds.*.source', 'url', function($data) {
return $data->type=='user';
});
$validator->sometimes('feeds.*.source', 'min:1|regex:/^[A-Za-z0-9\-]+$/', function($data) {
return $data->type=='newsapi';
});
}

You can use sometimes validation rule to achive your desired functionality. In the following code name will be validated every time when you make a request and source will be validated based on the type.
$validator = Validator::make($data, [
'name' => 'required|min:1|regex:/^[A-Za-z0-9_~\-!##\$%\^&\(\)\s]+$/',
]);
$validator->sometimes('feeds.*.source','url',function($input){
return $input->type=="user";
});
$validator->sometimes('feeds.*.source','min:1|regex:/^[A-Za-z0-9\-]+$/',function($input){
return $input->type=="newsapi"
});

Related

Why {} is a not valid JSON and how to validate empty JSON? [duplicate]

I'm making a Laravel API, but I can't seem to send JSON data in one of the posts. I checked the other posts in StackOverflow, but it seems that my JSON request is correct, so I can't seem to find the error:
Here is the code in my Controller's method:
$validator = Validator::make($request->all(), [
"name" => "required|string",
"colors" => "json",
"sizes" => "json"
]);
if($validator->fails())
return response()->json(["errors" => $validator->errors()], 400);
Here is the request body:
{
"name": "Test",
"colors": {
"Man": "#0000ff",
"Second": "#FF0000"
},
"sizes": {
"titles": "20px"
}
}
The error:
{
"errors": {
"colors": ["The colors must be a valid JSON string."],
"text_sizes": ["The text sizes must be a valid JSON string."]
}
}
What seems to be the problem? Thank you!
Well you need to pass an JSON String instead of an JSON Object. This can be done either by json_encode or JSON.stringify.
As an answer on your last comment.:
You could either do this in your frontend application with JSON.stringify or you could implement an Form Request with an prepareForValidation(): https://laravel.com/docs/8.x/validation#prepare-input-for-validation.
Where you would do an json_encode() on the json properties. Like:
protected function prepareForValidation()
{
$this->merge([
'colors' => json_encode($this->colors),
'text_sizes' => json_encode($this->text_sizes)
]);
}
Or in your case:
$validator = Validator::make($request->merge([
'colors' => json_encode($request->colors),
'text_sizes' => json_encode($request->text_sizes)
]), [
"name" => "required|string",
"colors" => "json",
"sizes" => "json"
]);
I found a simple solution, just use double quotes to represent a json string, and escape the double quotes inside the json:
{ "name": "Test", "colors": "{\"Man\": \"#0000ff\",\"Second\": \"#FF0000\"}", "sizes": "{\"titles\": \"20px\"}" }
This solve my issue sending json string from Insomnia Api rest.
laravel have a convenient way to validate a request please follow these steps to make your own request and response for api
1-php artisan make:request YourRequest
Then customize your request like this
<?php
namespace App\Http\Requests;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Http\Response;
class OrderRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules(): array
{
$rules = [
'your filed name' => 'required',
];
return $rules;
}
/**
* Get the error messages that apply to the request parameters.
*
* #return array
*/
public function messages()
{
return [
'your field name' => 'custom message',
];
}
/**
* Handle a failed validation attempt.
*
* #param Validator $validator
* #return void
*
* #throws ValidationException
*/
protected function failedValidation(Validator $validator)
{
$error = collect($validator->errors())->collapse()->toArray();
$errors = implode(' | ', $error);
throw new HttpResponseException(response()->json(
['response' => ['status' => false, 'message' => $errors]],
Response::HTTP_UNPROCESSABLE_ENTITY));
}
}
this will solve error as recommended by laravel and its a professional way
then use this Request into controller .
if you want to use your own code then
just use json_encode($this->text_sizes)

Laravel replace validation value not showing in validated() array

In my blade form, I have an input field that asks for a hour value, lets say input_stage_hour
I am trying to convert this to minutes AFTER validation, but BEFORE it hits my controller ... In my form request im using the passedValidation method to convert hours to minutes, then in my controller i am filling my model using $request->validated()
The problem is, it is passing through the original value and not the converted value.
My cut down form request is below;
public function rules()
{
return [
'input_stage_hour' => ['required', 'numeric', 'integer'],
];
}
protected function passedValidation()
{
$this->replace([
'input_stage_hour' => intval($this->input_stage_hour) * 60,
]);
}
If I pass a value like 2 into the input_stage_hour and then dd($request->validated()) in my controller, it still shows the value 2 instead of 120
The data that comes from that validated method on the FormRequest is coming from the Validator not the FormRequest itself. So if you really wanted to do this with the FormRequest and be able to call that validated method you would have to adjust the data the Validator is holding or adjust the validated method.
Example attempting to adjust the data the Validator is holding:
protected function passedValidation()
{
$data = $this->validator->getData();
$this->validator->setData(
['input_stage_hour' => $data['input_stage_hour'] * 60] + $data
);
}
If you wanted to override the validated method:
public function validated()
{
$data = parent::validated();
return ['input_stage_hour' => $data['input_stage_hour'] * 60] + $data;
}

is there any way to validate a field that sometime is File(image) && sometime is String(Src of same image)

my problem :
i am using laravel framework php
i want validate a field witch my field sometime is File(image) and sometime is String(src of same image)
is there any shortcut or solution in Laravel ???
The specifics of your question are not exactly clear but I think you can manage what you want by doing something like:
$request->validate([
'stringOrFile' => [
function ($attribute, $value, $fail) {
if (!is_string($value) && !($value instanceof UploadedFile)) {
$fail('The '.$attribute.' must either be a string or file.');
}
}
]
]);
Where UploadedFile refers to \Illuminate\Http\UploadedFile and stringOrFile refer to the name of the input your are validating.
However if possible use a different name for the input depending on what it is so you can have more complex validation rules on each different input.
More details on these kinds of validation rules in the manual
Actually while using the form data, empty image is received as a string "null". you can manage this in your controller.
$request->request->add(['image' => $request->image== "null" ? null : $request->image]);
$request->validate(['image'=> nullable|sometimes|image|mimes:jpeg,png,jpg,svg])
or you can send an empty string in case if image is not attached.
Or you can do something like that in your request class ;)
/**
* Get the validation rules that apply to the request.
*
* #return array<string, mixed>
*/
public function rules()
{
return [
'image' =>$this->getValidationRule('image'),
];
}
/**
* #param String $key
* #return string
*/
public function getValidationRule(String $key): string
{
if (request()->hasFile($key)) {
return "nullable|mimes:png,jpg";
}
return "nullable|string";
}
I use this code example. take any part useful for you.
$msg=[
'name.required'=>'<span class="badge">Name</span> is Required',
'username.required'=>'<span class="badge">User Name</span> is Required',
'born.required'=>'<span class="badge">User Name</span> is Required'
];
$request->validate([
'name'=>'required|string|min:2|max:30',
'username'=>'required|string|min:3|max:20',
'born'=>'required|date',
'image'=>'nullable|image|mimes:jpg,jpeg,bmp,png'
],$msg);
$msg for errors
you should create error page blade name error contains
#if($errors->any())
{!! implode('', $errors->all('<div class="alert alert-danger">:message</div>')) !!}
#endif
///
in blade that contain form for validation write top code
#include('error')
include error page if exist any error to display errors

Laravel: FormRequest does not return only validated data

i got object with some validationl, and the request validated method returns even fields that are not in validation rules. Here is how my validation class looks like.
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'terminal' => ['required'],
'terminal.followings' => ['boolean']
];
}
And this is how my json body on request looks like.
{
"client" : {
"pk" : "2128436070",
"username" : "miljan_rakita",
"daily_following" : 1000
},
"terminal" : {
"followings" : true,
"followingasdad" : "asdasdas",
"followers" : false,
"exact_account" : true
}
}
From this validation, i expect to get only this object:
{
"terminal" : {
"followings" : true,
}
}
But when i dd the validated data:
public function store(Test $request)
{
dd($request->validated());
}
Response is full terminal object, even non validated items.
array:1 [▼
"terminal" => array:4 [▼
"followings" => true
"followingasdad" => "asdasdas"
"followers" => false
"exact_account" => true
]
]
So i expect to get only terminal object with followings field with it. But i get all other fields that are in terminal object.
I can pull out only items i need from array, but i would like to know why i don't get only validated items.
The form validation only checks if the incoming request does at least contain all required values, so the request data you receive is as expected. Having said so you'd like to adjust the incoming data, which can be done in the latest release; laravel v5.8.33. You can do so by implementing the passedValidation() method in your formrequest (Test in your case).
public function passedValidation()
{
// '$this' contains all fields, replace those with the ones you want here
}

laravel URL Request validation error is not getting?

I am using Request Validation for validation. but when validation rule becomes fail then i am not getting that message like wrong name is given .
I use Make::Request Method
My Form Request code
namespace xx\xx\xxx\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class InstituteUpdateRequest 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($id=0)
{
return [
'name' => 'required|regex:/^[(a-zA-Z\s\-)]+$/u|min:3|max:80',
'valid_from' => 'date|max:30|nullable',
'valid_to' => 'date|nullable',
'address' => 'regex:/^[(a-zA-Z.\-,0-9\s)]+$/u|max:150',
'mobile' => 'required', Rule::unique('users')->ignore($id),
'city' => 'regex:/^[(a-zA-Z\-\s)]+$/u|max:100',
'state' => 'regex:/^[(a-zA-Z\-\s)]+$/u|max:100',
'pin' => 'max:6|regex:/^[(0-9)]+$/u',
];
}
}
My Controller code
public function update ( InstituteUpdateRequest $request )
{
DB::transaction(function () use ($request) {
$this->institute_update = Institute::where('class_code' ,$request->class_code)->update([
'name'=>$request->name ,
'valid_from'=>date('Y-m-d',strtotime($request->valid_from)) ,
'valid_to'=>date('Y-m-d',strtotime($request->valid_to)),
'mobile'=>$request->mobile,
'address'=>$request->address,
'city'=>$request->city,
'state'=>$request->states,
'pin'=>$request->pin,
'logo' => 'abc',
]);
});
}
my API Response
{"name":"Demo Institute 1BBBB","valid_from":"29-12-2017","valid_to":"20-12-2018","mobile":"9999999991","address":"Kolar","city":"Bhopal","state":"Madhya Pradesh","pin":"835553","logo":"","class_code":"940370037"}
this is my code.
In that case if i am passing wrong name Demo Institute 1BBBB. I am not getting error message. only redirect into my plugin page. that image i share here.
please tell me wt is going wrong.
I find my Solution by self. Actually i am not try to make request after login. So that it is being redirect to our plugin page.
But when i tried it after login then i got proper format of Error Message.

Categories