¿How i can capture errors from methos of controller in Laravel with Axios? The problem is the following, when the data passes through the validator of the myProfile method in the UserController in laravel and is correct, a json response is generated in the method and then Axios takes them and displays the toast Success message, but when i passes erroneous or empty data to the validor and this fails, Axios does not take the json with the error and shows me the empty toast and generates an error 422 in the console.
myProfile in User controller
public function myProfile(Request $request)
{
$valido = $this->validate($request, [
'firstname' => 'required|min:3|max:15',
'lastname' => 'min:2|max:15',
'gender' => 'numeric',
'description' => 'max:200',
]);
if($valido){
return response()->json([
'status' => 'success',
'msg' => 'Ok',
], 201);
}
else{
return response()->json([
'status' => 'error',
'msg' => 'Error',
], 422);
}
}
Profile.vue (Axios section)
updateUser(){
const value = {
'id': this.user.id,
'firstname': this.user.firstname,
'lastname': this.user.lastname,
'gender': this.user.gender,
'description': this.user.description,
}
axios.put('/dashboard/profile', value)
.then((response) => {
let title = response.data.status;
let body = response.data.msg;
this.displayNotificationSuccess(title, body);
})
.catch((error) => {
let title = error.response.data.status;
let body = error.response.data.msg;
this.displayNotificationError(title,body);
})
}
Screenshot when Axios capture json Success fron controller
Screenshot when Axios capture Success request
Screenshot when Axios not capture json error from controller
Error
Screenshot from console for json error no capture by axios
Error 422 in console
¿How i can solved that problem? I used Laravel 5.6, Vuejs 2 and Axios
If you wrap the validate() method call in a try/catch block, then you can catch the ValidationException thrown when the request is invalid. This will allow you to return your own response.
I've shown you an example of this below, and included the validation errors too, should you wish to output these on the front-end.
<?php
use Illuminate\Validation\ValidationException;
public function myProfile(Request $request)
{
try {
$this->validate($request, [
'firstname' => 'required|min:3|max:15',
'lastname' => 'min:2|max:15',
'gender' => 'numeric',
'description' => 'max:200',
]);
return response()->json([
'status' => 'success',
'msg' => 'Okay',
], 201);
}
catch (ValidationException $exception) {
return response()->json([
'status' => 'error',
'msg' => 'Error',
'errors' => $exception->errors(),
], 422);
}
}
Related
blog:{
postTitle: '',
}
this is in JS
let data = new FormData();
const blog = JSON.stringify(this.blog);
data.append('blog',blog);
Laravel
$blog = json_decode(request('blog'));
$blog->validate([
'blog.postTitle' => 'required'
]);
I have tried to:
after I decode it I have tried to:
return $request['blog']
and it works.
Error for validation I get is:
Call to undefined method stdClass::validate()
I am sending blog object(without JSON.stingify()), and now validation works.
await this.setCreatePost({data, blog})
request()->validate([
'blog.postTitle' => 'required|max:100|string',
'blog.sectionTitles.*.title' => 'required|string|max:100',
'blog.sectionTitles.*.belongsTo' => 'required|integer|max:1',
'blog.textareas.*.text' => 'required|string|max:500',
'blog.textareas.*.belongsTo' => 'required|integer|max:1',
]);
I have a Laravel 8 app that uses Botman. When I call the endpoint from Postman, I get the correct content with the correct headers. But when I call the endpoint while testing I get empty content and thus the test doesn't pass. The response is handled by HttpFoundation JsonResponse. The weird thing is the content is printed in the test console (even when I don't dump) but, $response->dump() returns Null.
My test method
/** #test */
public function user_can_talk_to_coach()
{
Passport::actingAs($this->learner, $this->learnerScopes);
$response = $this->postJson(
'learner/v1/coach',
[
'driver' => 'mobile',
'userId' => 1,
'message' => null,
'intent' => 'intent_testing',
],
$this->headers
);
var_dump('dump');
$response->dump();
var_dump('headers');
$response->dumpHeaders();
$response->assertStatus(200)
->assertJson([
'data' => [
[
'type' => 'text',
'text' => 'Hey',
'attachment' => null,
'additionalParameters' => [
'node'=> 'testing',
],
],
],
]);
}
Message sending method
/**
* Send out message response.
*/
public function messagesHandled()
{
$messages = $this->buildReply($this->replies);
// Reset replies
$this->replies = [];
$response = new JsonResponse();
$response->setData(['data' => $messages]);
$response->send();
}
Test result capture
Any idea of what is happening here ?
I'm struggling to upload an image and several text/numeric data fields to a MySQL DB with Vue, Laravel, and Axios.
Here's the method in my Vue component:
addProductToShop() {
const imageData = this.$refs.inputUpload.files[0];
const formData = new FormData();
formData.append("image", imageData);
axios
.post("api/createProduct", {
formData,
...this.newProduct
})
.then(res => {
console.log(res);
});
},
And here's the method in my Laravel controller:
public function create(Request $request)
{
$product = Product::create([
'name' => $request->name,
'price' => $request->price,
'amountInStock' => $request->amountInStock,
'image' => $request->image->store('ProductImages', 'public'),
'measuringUnitId' => $request->measuringUnitId,
'categoryId' => $request->categoryId,
'shopId' => $request->shopId,
]);
return response()->json([
'status' => 'success',
'message' => 'Product added seccessfully',
'product' => $product
], 200);
}
Here's the request body in telescope:
{
"formData": [],
"name": "111",
"categoryId": null,
"price": "111",
"amountInStock": "111",
"measuringUnitId": 2,
"visability": true
}
And here's the error that i'm getting: Call to a member function store() on null
I've tried adding multi-form data headers:
headers: {
'Content-Type': 'multipart/form-data'
}
However, they generated this error: Missing boundary in multipart/form-data POST data in Unknown on line 0
So, they seem obsolete now, because axios knows the corrent formData based on the FormData().
Can someone point out what am i doing wrong? Thanks in advance!
Error here:
'image' => $request->image->store('ProductImages', 'public')
Correct way:
'image' => $request->file('image')->store('ProductImages', 'public')
I have a method that captures the information sent by the vue view (Profile.vue) through a PUT generated by Axios, the problem lies in the following, when the data is updated (using the myProfile method of the UserController), axios captures the information of the return in json from the method, and the success message is shown, but when there is an error, Axios does not capture the error json information and alleges the following:
Uncaught (in promise) TypeError: Cannot read property 'status' of undefined
I understand that you are alleging to me by the variables that I have in the catch section of Axios that do not have information.
myProfile code (UserController)
$profile = User::find(Auth::user()->id);
$profile->firstname = $request->firstname;
$profile->lastname = $request->lastname;
$profile->gender = $request->gender;
$profile->description = $request->description;
if($profile->update())
{
return response()->json([
'status' => 'Muy bien!',
'msg' => 'Datos actualizados correctamente.',
'cod' => 201
]);
}
else{
return response()->json([
'status' => 'Ocurrio un error!',
'msg' => 'Ocurrio un error al actualizar la información.',
'cod' => 400
]);
}
Axios section of Profile.vue
axios.put('/dashboard/profile', value)
.then((response) => {
let title = response.data.status;
let body = response.data.msg;
this.displayNotificationSuccess(title, body);
})
.catch((response) => {
let title = response.data.status;
let body = response.data.msg;
this.displayNotificationError(title,body);
})
As I said before, when there is success in the controller, Axios reads and shows the message json, when there is an error, it does not.
Where am I failing that Axios can not show the erro json message coming from the controller?
I used Laravel 5.6, Vuejs 2 and Axios
In the catch callback, the argument is the error object, not the response object. Try this:
axios.put('/dashboard/profile', value)
.then((response) => {
let title = response.data.status;
let body = response.data.msg;
this.displayNotificationSuccess(title, body);
})
.catch((error) => {
let title = error.response.data.status;
let body = error.response.data.msg;
this.displayNotificationError(title,body);
})
SOURCE
First - you have to define in your backend that the second part is actually an error, otherwise axios will see it as a successful request.
You do that by putting an error status code as a 2nd argument to response()->json(json, code). You can see a list of status codes here.
Example:
return response()->json([
'status' => 'Ocurrio un error!',
'msg' => 'Ocurrio un error al actualizar la información.',
'cod' => 400
], 400);
Second, axios .catch() returns an error, not the response. In order to get the response, you have to call err.response on it.
Example:
.catch((response) => {
let title = response.response.data.status;
let body = response.response.data.msg;
this.displayNotificationError(title,body);
})
I have a route group that looks like this:
Route::group(['prefix' => 'recipe','middleware'=>['auth.basic']], function (){
//Some things to do
});
When credentials are invalid Laravel outputs "Invalid credentials." How do I override this response with my own JSON response?
In AuthController, try this :
public function postLogin(Request $request)
{
$this->validate($request, [
'email' => 'required', 'password' => 'required',
]);
$credentials = [
'email' => $request->input('email'),
'password' => $request->input('password')
];
if (Auth::attempt($credentials, $request->has('remember')))
{
return redirect()->intended($this->redirectPath())
->with('success', 'You are successfully logged in');
}
return Response::json(array(
'success' => false,
'errors' => $this->getFailedLoginMessage(),
));
}
I just had a look at the Illuminate\Auth\SessionGuard. The method getBasicResponse() seems to be responsible for the response on a failed login attempt (with basic auth).
protected function getBasicResponse()
{
$headers = ['WWW-Authenticate' => 'Basic'];
return new Response('Invalid credentials.', 401, $headers);
}
How to actually overwrite it seems a little tricky though. You probably need to extend the SessionGuard Class and implement your own getBasicResponse() method. Thats the easy part, how to actually instantiate your own guard instead of the default one, I don't know yet.