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.
Related
I made a controller to store tasks, it looks like:
public function store(StoreTaskRequest $request)
{
$validated = $request->validated();
return response()->json($request);
}
For the request validation i made a custom validator, that looks like
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreTaskRequest 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 [
'project_id' => 'required',
'project_name' => 'required',
'task_id' => 'required',
'task_name' => 'required',
'startDate' => 'required',
'endDate' => 'required',
];
}
public function messages()
{
return [
'project_id.required' => 'required!',
'project_name.required' => 'required!',
'task_id.required' => 'required!',
'task_name.required' => 'required!',
'startDate.required' => 'required!',
'endDate.required' => 'required!',
];
}
}
When i make a post request to that controller with incorrect data it returns an html page but when i post it with the correct data it returns the request as json
By the way i make my post request with: reqbin.com
Post request headers:
X-Csrf-Token: ....
Content-Type: application/json
Post Params:
{
"project_name": "Wiza",
"task_id": 1,
"task_name": "test 1",
"startDate": {
"week": 1,
"start" : 11,
"year": 2022
},
"endDate": {
"week": 1,
"start" : 11,
"year": 2022
}
}
Does anyone have any idea why its returning a html page instead of an validation error?
Edit:
api.php is empty
web.php
Route::post('api/v1/tasks/', [TaskController::class, 'store']);
//Also tried
Route::resource('api/v1/tasks/', TaskController::class);
Add this code in your custom validator.
/**
* Get the error messages for the defined validation rules.*
* #return array
*/
protected function failedValidation(ValidationValidator $validator)
{
throw new HttpResponseException(response()->json([
'message' => implode('', collect($validator->errors())->first()),
'status' => true
], 422));
}
I have faced the same problem and below mentioned way works for me.
Header Debugging
First You need to verify the list of headers exists in your request. You can do this by following the below code in your controller store method:
public function store(StoreTaskRequest $request)
{
dd($request->headers); //dump your headers exists in $request
$validated = $request->validated();
return response()->json($request);
}
and that will show you something like:
Solution:
Bestway and clean way to append those headers by using middleware i.e.
I've created ForceJsonResponse middleware.
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class ForceJsonResponse
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle(Request $request, Closure $next)
{
$request->headers->set('Accept', 'application/json');
return $next($request);
}
}
after that, I've registered that middleware in app/Http/Kernel.php as shown in the screenshot.
then attach that middleware with that route as shown in the screenshot:
laravel doc reference for middleware attachement
Worst case scenario
if still, it doesn't work then you can use try catch statement
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)
I've an update form that contains an image and other data to be updated I changed the default route key to use the name instead of the default key which is the ID and I made a separate form request to validate my requests It works fine when posting new record unfortunately it keeps failing with the name field which is unique field; I've checked all threads on github and in stackoverflow with no use although I have the same project in laravel 5.5 and it works fine and now I'm stuck with laravel 6
hereis my form
let data = new FormData();
data.append('name', this.channel.name);
data.append('base_color', this.channel.baseColor);
data.append('complementary_color', this.channel.complementaryColor);
if (this.file){
data.append('avatar', this.file);
}
data.append('_method', 'PUT');
axios.post(`/dashboard/channels/${this.channel.name}`, data).then(resp => {
this.$parent.$emit('channel_updated', resp.data);
}).catch(error => {
flash(error.response.data, 'danger', 'backEndStyle');
});
and here is my route
Route::resource('/dashboard/channels', 'ChannelController');
and here is my form request
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ChannelRequest 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|unique:channels,name,'. $this->id,
'base_color' => 'required',
'complementary_color' => 'required',
];
}
}
here is my controller for update method
public function update(Channel $channel, ChannelRequest $request)
{
$channel->update([
'name' => $request->name,
'bg_base_color' => $request->base_color,
'bg_complementary_color' => $request->complementary_color,
]);
return response($channel->fresh(), 200);
}
Use the ignore constraint to ignore the current model when validating unique
public function rules()
{
return [
'name' => ['required', Rule::unique('channels')->ignore($this->route('channel'))],
'base_color' => 'required',
'complementary_color' => 'required',
];
}
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"
});
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 years ago.
Improve this question
I have my custom Request, which extends the Backpack CrudController.
Now I would like to override the prepareForValidation of the ValidatesWhenResolvedTrait since it looks like the right place to modify my incoming data, but I can't figure out how ...
So my first question is, can I override this method? Its protected ...
protected function prepareForValidation()
And my second question, how can I modify my input on the Request or FormRreuqest objects?
Here is my RequestClass
<?php
namespace App\Http\Requests;
use App\Http\Requests\Request;
use Config;
class DonationsRequest extends \Backpack\CRUD\app\Http\Requests\CrudRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
// only allow updates if the user is logged in
return \Auth::check();
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'name' => 'required|max:255',
'email' => 'required|email',
'dob' => 'required|date',
'newsletter' => 'required|boolean',
'country' => 'sometimes|required|in:'.implode(',', Config::get('validation.countries')),
'street' => 'sometimes|required|string|max:255',
'zip' => 'sometimes|required|string|between:4,5',
'city' => 'sometimes|required|string|between:4,255',
'amount' => 'required|numeric|between:1,'.Config::get('donations.max'),
'type' => 'required|in:oo,monthly',
'provider' => 'sometimes|string|nullable',
'product_id' => 'sometimes|exists:products,id|nullable',
'campaign_id' => 'required|exists:campaigns,id',
'status' => 'sometimes|required|in:pending,canceled,success,error',
'profile' => 'sometimes|string|regex:/^profile[0-9]+$/|nullable',
];
}
/**
* Get the validation attributes that apply to the request.
*
* #return array
*/
public function attributes()
{
return [
//
];
}
/**
* Get the validation messages that apply to the request.
*
* #return array
*/
public function messages()
{
return [
//
];
}
private function prepareForValidation()
{
dd('getValidatorInstance custom');
$this->sanitizeInput();
return parent::getValidatorInstance();
}
private function sanitizeInput()
{
dd('sanitizeInput custom');
$data = $this->all();
dd($data);
// overwrite the newsletter field value to match boolean validation
$data['newsletter'] = ($data['newsletter'] == 'true' || $data['newsletter'] == '1' || $data['newsletter'] == true) ? true : false;
return $data;
}
private function validate() {
dd('validate');
}
}
As you can see, I first tried to override the getValidatorInstance method, since this looked like the common aproach to this, but it is not executed (so not overridden - protected?).
Although I didn't tried but it seems it should work you can override validationData from Illuminate\Foundation\Http\FormRequest class like.
/**
* Get data to be validated from the request.
*
* #return array
*/
protected function validationData()
{
$all = parent::validationData();
//e.g you have a field which may be json string or array
if (is_string($playerIDs = array_get($all, 'player_id')))
$playerIDs = json_decode($playerIDs, true);
$all['player_id'] = $playerIDs
return $all;
}
or you can override all method in Illuminate\Http\Concerns\InteractsWithInput trait
/**
* Get all of the input and files for the request.
*
* #return array
*/
public function all()
{
$all = parent::all();
//then do your operation
if (is_string($playerIDs = array_get($all, 'player_id')))
$playerIDs = json_decode($playerIDs, true);
$all['player_id'] = $playerIDs
return $all;
}
Could you modify the request?
$request->merge(['field' => 'new value']);
Well I am sure,this can help in modifying The input, it worked for me.[laravel 5.4]
place this
$input['url'] = $url;
$this->replace($input);
dd($input);
in listFormRequest. (use $all instead of $input, if you follow above used answer).
This only changes input,which is available even in controller. You still need to find a way to insert it into DB, or do something else to use modified input for using it in blade.
Ok I found out where the error was. I did split the Frontend Request and the Backend Request Call. Since I was working on the Backend Request the Frontend Request was not overwriting anything ... so it was my bad, no bug there, sry for the waste of time, but a big thanks to the community!