Empty array when passed to response()->json - php

I have a method in parent class
Controller.php
public function invalidError($errors = [], $code = 422)
{
return response()->json([
'errors' => $errors
], $code);
}
I am passing this method the following:
if($validator->fails()) {
return $this->invalidError([
array('key' => 'Some key')
]);
}
When the response comes in the errors message is always empty array like the following:
{
"errors": []
}
What am I missing?

To get the errors array from a validator, use failed()
if($validator->fails()) {
return $this->invalidError($validator->failed());
}
If you wants the messages from the failed rules use messages()
if($validator->fails()) {
return $this->invalidError($validator->messages());
}
For more information, you can check the documentation

Related

How to deal with conditioned based validation in laravel?

I have a situation and unfortunately not sure how to sort it out in proper way. I have below script
$validator = Validator::make(
$request->all(),
[
'game_id' => 'required|integer'
],
$messages
);
if ($validator->fails()) {
$response = $validator->messages();
}else{
$response = $gameService->setStatus($request);
}
Now each game has different type, I wanted to add validation on behalf of type. For example if a game is Task Based then I would add validation for time which would be mandatory only for Task based game otherwise it would be an optional for other types.
I have three types of games
1 - level_based
2 - task_based
3 - time_based
In the type table, each game has type.
So is there any way to add validation? I want to do it, inside validation function.
Thank you so much.
You can write your conditions before the validation.
$data = $request->all();
if ($data['game_id'] == 1) {
$rules = [
// level_based validation
];
} else if($data['game_id'] == 2) {
$rules = [
// task_based validation
];
} else {
$rules = [
// time_based validation
];
}
$validator = Validator::make($data, $rules);
Hope it helps. Cheers.
I would go with the required_if validation rule.
So in your case, will send two fields, the type can be a hidden field for example, then on the game_id you will add
'game_id' => 'required_if:type,1'
and so on.. And of course you can customize the error messages.
Try this code snippet
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class CreateGameRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
try {
$request = $this->request->all();
$rule_array = collect();
$rule1 = [
'game_id' => 'required|integer'
]
$rule_array = $rule_array->merge($rule1);
if(isset($request->task_id))
{
$rule2 = [
'task_id' => 'required|integer'
]
}
$rule_array = $rule_array->merge($rule2);
return $rule_array->all();
} catch (Exception $e) {
return $e;
}
}
public function messages(){
return [
'game_id' => 'Please select valid game',
'task_id' => 'Please select valid task'
];
}
}
then invoke this request class in controller function as
use App\Http\Requests\CreateGameRequest;
public function game(CreateGameRequest $request)
{
}

How to add a custom validation rule in Laravel?

I would like to add custom validations rules on my Laravel Controller:
The container exists in the database
The logged user is owner of the resource
So I wrote this:
public function update($id, Request $request) {
$validator = Validator::make($request->all(), [
'name' => 'required|unique:stock.containers|max:255'
]);
$container = Container::find($id);
if(!$container)
{
$validator->errors()->add('id', 'Not a valid resource');
}
if($container->owner_id != user_id())
{
$validator->errors()->add('owner_id', 'Not owner of this resource');
}
if ($validator->fails()) {
return response()->json($validator->errors(), 422); //i'm not getting any
}
}
Unfortunately the $validator->errors() or even $validator->addMessageBag() does not work. I noticed $validator->fails() clears the error messages and adding an error will not make the validation to fail.
What is the proper way to achieve this?
Then you can use after:
public function update($id, Request $request) {
$validator = Validator::make($request->all(), [
'name' => 'required|unique:stock.containers|max:255'
]);
$validator->after(function($validator) use($id) {
$container = Container::find($id);
if(!$container)
{
$validator->errors()->add('id', 'Not a valid resource');
}
if($container->owner_id != user_id())
{
$validator->errors()->add('owner_id', 'Not owner of this resource');
}
});
if ($validator->fails()) {
return response()->json($validator->errors(), 422); //i'm not getting any
}
}

return first error in customized formatted in laravel 5.5 form requests

Before laravel 5.5 I used a form request like this with a customized format :
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
class StoreProductRequest extends FormRequest
{
public function authorize ()
{
return true;
}
public function rules ()
{
return [
'title' => 'required',
'desc' => 'required',
];
}
public function response (array $errors)
{
return response()->json($errors, 200);
}
protected function formatErrors (Validator $validator)
{
$result = ['success' => false, 'msg' => $validator->errors()->first()];
return $result;
}
}
Means when an error occured, only the first error returned as a json format like this :
{
"success" : "false",
"msg" : "title field is required "
}
But seem that in laravel 5.5 in this way could not format error like this.
Now I want to return error exactly same format I mentioned above in json format but I do not know How can
This functionality was changed in Laravel 5.5. From the upgrade guide "A Note On Form Requests":
If you were customizing the response format of an individual form request, you should now override the failedValidation method of that form request, and throw an HttpResponseException instance containing your custom response
Your updated Form Request might look something like this (pseudo-code, not tested):
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
class StoreProductRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'title' => 'required',
'desc' => 'required',
];
}
public function failedValidation(Validator $validator)
{
throw new HttpResponseException(
response()->json(['success' => false, 'msg' => $validator->errors()->first()], 400)
);
}
}
protected function formatErrors (Validator $validator)
{
$result = ['success' => false, 'msg' => $validator->errors()];
return $result;
}
Expanding on #Aken Roberts answer. Since this is an error response for a form, I use the error key (input field name) to display the error beside the input.
You can get the first error key from the keys method. With Laravel 5.7 this works as expected:
public function failedValidation(Validator $validator)
{
throw new HttpResponseException(
response()->json([
'success' => false,
'error' => (object) [
$validator->errors()->keys()[0] => $validator->errors()->first()
]
], 400)
);
}

For Laravel, How to return a response to client in a inner function

I'm building an api using laravel, the issue is when the client requests my api by calling create() function, and the create()function will call a getValidatedData() function which I want to return validation errors to the client if validation fails or return the validated data to insert database if validation passes, my getValidatedData function is like below so far
protected function getValidatedData(array $data)
{
// don't format this class since the rule:in should avoid space
$validator = Validator::make($data, [
'ID' => 'required',
'weight' => 'required',
]);
if ($validator->fails()) {
exit(Response::make(['message' => 'validation fails', 'errors' => $validator->errors()]));
}
return $data;
}
I don't think exit() is a good way to return the errors message to clients. are there any other ways I can return the laravel Response to clients directly in an inner function. use throwing Exception?
This was what worked for me in Laravel 5.4
protected function innerFunction()
{
$params = [
'error' => 'inner_error_code',
'error_description' => 'inner error full description'
];
response()->json($params, 503)->send();
}
What you can do is using send method, so you can use:
if ($validator->fails()) {
Response::make(['message' => 'validation fails', 'errors' => $validator->errors()])->send();
}
but be aware this is not the best solution, better would be for example throwing exception with those data and adding handling it in Handler class.
EDIT
As sample of usage:
public function index()
{
$this->xxx();
}
protected function xxx()
{
\Response::make(['message' => 'validation fails', 'errors' => ['b']])->send();
dd('xxx');
}
assuming that index method is method in controller you will get as response json and dd('xxx'); won't be executed
You can use this method
public static function Validate($request ,$rolse)
{
// validation data
$validator = Validator::make($request->all(),$rolse);
$errors = $validator->getMessageBag()->toArray();
$first_error = array_key_first($errors);
if (count($errors) > 0)
return 'invalid input params , ' . $errors[$first_error][0];
return false;
}
in controller :
$validate = ValidationHelper::Validate($request,
['title' => 'required']);
if ($validate)
return response()->json(['message' =>'validation fails' , 'error'=> $validate], 403);

How to format the validation error messages in Laravel 5?

I am building a RESTful API with Laravel 5.1 - When a post request is made, I validate the input, if the input is not valid, I throw an exception.
Current Response Sample:
{
"message": "{\"email\":[\"The email field is required.\"]}",
"status_code": 400
}
How to make my response look like this:
{
"message": {
"email": "The email field is required."
},
"status_code": 400
}
Here's how I throw the exception:
$validator = Validator::make($this->request->all(), $this->rules());
if ($validator->fails()) {
throw new ValidationFailedException($validator->errors());
}
I think the best way to validate the form in laravel is using Form Request Validation .You can overwrite the response method in App\Http\Request.php class.
Request.php
namespace App\Http\Requests;
Illuminate\Foundation\Http\FormRequest;
abstract class Request extends FormRequest
{
public function response(array $errors)
{
return $this->respond([
'status_code' => 400 ,
'message' => array_map(function($errors){
foreach($errors as $key=>$value){
return $value;
}
},$errors)
]);
}
/**
* Return the response
*/
public function respond($data , $headers=[] ){
return \Response::json($data);
}
}
You can try this:
$messages = [
'email.required' => 'The :attribute field is required.',
];
$validator = Validator::make($input, $rules, $messages);
Here is a class I use:
<?php
namespace App;
class Hack
{
public static function provokeValidationException($field_messages){
$rules = [];
$messages = [];
foreach($field_messages as $field=>$message){
$rules[$field] = 'required';
$messages[$field. '.required'] = $message;
}
$validator = \Validator::make([], $rules, $messages);
if ($validator->fails()) {
throw new \Illuminate\Validation\ValidationException($validator);
}
}
}
Then any time I need to show custom errors, I do:
\App\Hack::provokeValidationException(array(
'fieldname'=>'message to display',
'fieldname2'=>'message2 to display',
));
I had this same issue and I resolved it by decoding my the $validator->errors() response
return (400, json_decode($exception->getMessage()));

Categories