Format validation error message as nested associative array - laravel

I have a Json object of data as shown below
{
"name": "something",
"location": {
"city": "some where",
"country": "some where",
}
}
Rule used to validate Request is
[
'name' => 'required',
'location.city' => 'required',
'location.country' => 'required'
]
Which returns error message like
{
"name": [
"The name field is required."
],
"location.city": [
"The location.city field is required."
],
"location.county": [
"The location.country field is required."
]
}
How can I format error message as a nested array like the Request.
{
"name": [
"The name field is required."
],
"location": {
"city": [
"The city field is required"
],
"country": [
"The country field is required"
]
}
}
Any default methods available ?
I am using Illuminate\Foundation\Http\FormRequest

In your case , you need to build the error message yourself. you can still use the default messages in the ressources/lang/en/validation messages file.
$validator = Validator::make($request->all(), [
'name' => 'required',
'location.city' => 'required',
'location.country' => 'required'
]);
if ($validator->fails()) {
return response()->json($yourOwnFormat,422);
//you can use $validator->errors() to build it
}

For those who looking for the solution This is how I implemented
<?php
namespace App\Http\Requests;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
class UserStoreRequest extends FormRequest
{
public function rules()
{
return [
'name' => 'required',
'location.city' => 'required'
'location.country' => 'required'
];
}
public function attributes()
{
return [
'location.city' => 'City'
'location.country' => 'Country'
];
}
protected function failedValidation(Validator $validator)
{
$errors = $validator->errors()->getMessages();
$errors_formated = array();
foreach ($errors as $key => $value) {
array_set($errors_formated, $key, $value);
}
throw new HttpResponseException(response()->json(['error' => $errors_formated], 422));
}
}
The result of $validator->errors()->getMessages() is just like array_dot() helper function result. So I did the Opposite of array_dot(), also altered my attribute name into pretty name

Is it? Laravel Documentation- Customizing the Error Messages
public function messages()
{
return [
'location.city' => 'The city field is required',
'location.county' => 'The county field is required',
];
}

Related

How can create a test in laravel for check load relationships

public function test_show_role_should_return_actions()
{
$this->actingAs($this->user, 'api');
$this->withHeaders(['Accept' => 'application/json',])
->get(route('roles.show', ['role' => $this->role->id]))
->assertJsonStructure([
"data" => [
"name",
"actions" => [
"name",
"code"
]
]
]);
}
when I run the test,I have this error:
Tests\Feature\Role\RoleTest::test_show_role_should_return_actions
Failed asserting that an array has the key 'name'.
Even when I remove the "name",I get an error for the "actions" key.
public function test_show_role_should_return_actions()
{
$this->actingAs($this->user, 'api');
$this->getJson(route('roles.show', ['role' => $this->role->id]))
->assertJsonStructure([
'data' => [
'*' => [
'name',
'actions' => [
'*' => [
'name',
'code'
]
]
]
]
]);
}

L8 - API - Form Request on optional input JSON object

I'm working on Form Request and I've a question about how to use it with optional input object.
My API get a simple input JSON like:
{
"user": [
{
"name": "Valentino",
"car": {
"model": "ferrari",
"color": {
"front": "red",
"back": "black"
}
}
},
"name": "Stefano",
"car": {
"model": "mercedes"
}
}
]
}
the Controller:
public function insertUser(StoreUserRequest $request) {
}
the For Request Validation Class:
public function rules()
{
return [
'user' => 'required|array',
'user.*.name' => 'string|required',
'user.*.car' => 'required|array',
'user.*.car.model' => 'required|string',
'user.*.car.color' => 'nullable|array', // could be present or not
'user.*.car.color.front' => 'required|string', // should be validated only if exists 'color'
'user.*.car.color.back' => 'required|string', // should be validated only if exists 'color'
];
}
the color object could be optional into the input JSON; how I can set StoreUserRequest.php class to validate the color object only if exists?
Thank you very much!
#Tippin tell me a solution using required_with rule:
public function rules()
{
return [
'user' => 'required|array',
'user.*.name' => 'string|required',
'user.*.car' => 'required|array',
'user.*.car.model' => 'required|string',
'user.*.car.color' => 'nullable|array', // could be present or not
'user.*.car.color.front' => 'required_with:user.*.car.color|string',
'user.*.car.color.back' => 'required_with:user.*.car.color|string',
];
}
Thanks

How to custom response JSON object validator

i have problem with response validator like this :
{
"email": [
"The email field is required."
],
"password": [
"The password field is required."
]
}
im want to like this :
{
"email":
"The email field is required."
,
"password":
"The password field is required."
}
this my validator
$validator = Validator::make($request->all(), [
'email' => 'required|email',
'password' => 'required',
]);
if ($validator->fails()) {
return response()->json($validator->errors(), 400);
}
everyone can help me ? thanks very much

Laravel: How to access Object inside an array

I trying to return access the attributes inside a array of object and it is giving this error Exception: Property [id] does not exist on this collection instance.
Here is what I have tried:
protected function formatted($classroom)
{
return [
'courses' => [
'id' => $classroom->courses->id,
'name' => $classroom->courses->name,
'slug' => $classroom->courses->slug,
'coursteachers' => [
'id' => '$classroom->courses->coursteachers->id',
'email' => '$classroom->courses->coursteachers->email',
'uid' => '$classroom->courses->coursteachers->uid',
]
],
];
}
And here is the actual data:
"courses": [
{
"id": 1,
"name": "Analytics",
"slug": "analytics",
"status_id": 1,
"deleted_at": null,
"pivot": {
"classroom_id": 2,
"courses_id": 1
},
"coursteachers": [
{
"id": 3,
"uid": "S0120-46890",
"email": "teacher#vschool.com",
"user_type": "Teacher",
}]
}]
You need to iterate through courses and also courseteachers since they both represent an array but rather an object
protected function formatted($classroom)
{
$result = [];
foreach($classroom->courses as $course) {
$result[] = [
'courses' => [
'id' => $classroom->courses->id,
'name' => $classroom->courses->name,
'slug' => $classroom->courses->slug,
'coursteachers' => $this->getCourseTeachers($cours)
],
];
}
return $result;
}
private function getClassroomTeachers($classroom) {
$result = [];
foreach($classroom->courses as $cours)
{
foreach ($cours->coursteachers as $key => $teacher) {
$result[] = [
// 'coursteachers'=> [
'id' => $teacher->id,
'email' => $teacher->email,
'uid' => $teacher->uid,
'last_name' => $teacher->profile->last_name,
'first_name' => $teacher->profile->first_name,
'middle_name' => $teacher->profile->middle_name,
// ],
];
}
}
return $result;
}
Since courses is an array, you should pick an object using the proper index.
Foe example: try $classroom->courses[0]->id instead of $classroom->courses->id. Here, '0' is the index.
Also it is better if you check if the index exists before you do it. For an example.
'id' : isset($classroom->courses[$index]) ? $classroom->courses[$index]->id : ''
Edit:
In case of a Eloquent collection you should use $classroom->courses->get($index)->id instead of array like retrieval.

Laravel 5.8 ManyToMany relationship child relation usign foreign key doesn't work

When I call my image resource it returns the correct data from my model:
Image resource:
return [
'id' => $this->id,
'name' => $this->name,
'presentation' => $this->presentation->description,
'slug' =>$this->filename
];
Image Model:
public function presentation()
{
return $this->hasOne(ProductPresentation::class, 'id', 'presentation_id');
}
Returns:
{
"data": [
{
"id": 1,
"name": "White Gold",
"presentation": "Product x",
"slug": "products/white-gold.jpg"
}
}
But when I call the manyToMany (Products -> images) relation I only get the the Id not the foreign relation
"data": [
{
"id": 1,
"name": "White Gold",
"price": "€ 10,00",
"images": [
{
"id": 1,
"name": "White Gold",
"filename": "products/white-gold.jpg",
"presentation_id": 1
}
]
},
The Products resource calls the image resource but this doesn't load the relation ( need "presentation": "Product x" instead of "presentation_id": 1)
Using resource:
return [
'id' => $this->id,
'name' => $this->name,
'price' => $this->formattedPrice,
'images' => $this->images
];
using model:
public function images()
{
return $this->belongsToMany(Image::class);
}
So the question would be how do I add the relation to belongsToMany(Image::class)
Try to change
return [
'id' => $this->id,
'name' => $this->name,
'price' => $this->formattedPrice,
'images' => $this->images
];
To
return [
'id' => $this->id,
'name' => $this->name,
'price' => $this->formattedPrice,
'images' => YourImageResource::collection($this->images)
];

Resources