The validation on my Laravel 4.2 project was done with Ardent package. After going to Laravel 5.5 I have eliminated Ardent and wanted to do Laravel's native validation with form requests.
The problem I have is that the Ajax call was validated before like this:
public function postRegisterAjax(A)
{
try {
...
} catch (ExceptionBag $e) {
$msg = $e->getMessageBag()->all(':message');
$status = Status::ERROR;
}
return $this->responseJson($status, $msg);
}
Now I introduced UserValidationRequest class and I would like Ajax call to throw me an error message without the need to reload the page. In order to do that, I need to forward status and message as Json response.
I somehow tried to do that with after validation hooks, but it doesn't work:
protected function getValidatorInstance()
{
$validator = parent::getValidatorInstance();
if ($validator->fails()) {
\Log::info($validator->errors());
$msg = $validator->errors();
$status = Status::ERROR;
return response()->json(['response' => [
'status' => $status,
'msg' => $msg,
]]);
}
return $validator;
}
The code fails on return response() saying that Method passes does not exist (Illuminate/Support/Traits/Macroable.php:96).
Does anyone know what seems to be the issue?
From Laravel 5.x version (not sure), failedValidation() method was introduced in form requests instead of what Laravel 4.x had as response().
I resolved my issue by tailoring the response to my needs by overriding that method in my form request:
public function failedValidation(Validator $validator)
{
if ($validator->fails()) {
$status = Status::ERROR;
throw new HttpResponseException(response()->json(["response" => [
'msg' => $validator->errors()->all(':message'),
'status' => $status
]]));
}
return response()->json(["response" => [
'msg' => 'User successfully registered',
'status' => Status::SUCCESS
]]);
}
Related
As we know that in Laravel, we can validate a request by $request->validate() method that automatically redirect the user if validation failed.
I am trying to develop a function with a similar feature only difference is that, instead of redirecting the user, this function will send a JSON response on validation failure.
Here is my code
<?php
namespace App\Libs;
use Illuminate\Http\Request as RequestCore;
use Illuminate\Support\Facades\Validator;
class Request extends RequestCore {
public function validateAjax($data){
$input = $this->all();
$validator = Validator::make($input,$data);
if ($validator->fails()) {
return response()->json([
"errors" => $validator->errors(),
"message" => "Invalid Input"
], 401);
}
return true;
}
}
Problem is, when i run the code, It doesn't stop on error. What am i missing?
You should make new Request class (php artisan make:request ExampleRequest). And after add this function in that class for JSON response
protected function failedValidation(Validator $validator)
{
$errors = (new ValidationException($validator))->errors();
throw new HttpResponseException(
response()->json(['status' => 'error', 'errors' => $errors], JsonResponse::HTTP_UNPROCESSABLE_ENTITY)
);
}
Hi guys I'm working on API but I need to validate some data at backend, in this case, we only need a postman to send parameters and headers.
All is working fine now but I need more useful data in each request, Laravel has by default a Validator Form Request Validation, but I donĀ“t know how to use at API side.
I need to send the error message in JSON to Postman.
I found two options, one, make validations into a controller but seems to much code and the other make a php artisan make:request StoreObjectPost and then import the request into the controller and change the request of the store method, which one do you recommend, Ty!
You could instantiate the validator yourself like this:
$validator = Validator::make($request->all(), [
'name' => 'min:5'
]);
// then, if it fails, return the error messages in JSON format
if ($validator->fails()) {
return response()->json($validator->messages(), 200);
}
$PostData = Input::all();
$Validator = Validator::make(array(
'name' => $PostData['name']
), array(
'name' => 'required'
));
if ($Validator->fails()) { //if validator is failed
return false;
} else {
// do some thing here
}
Hope this may help you
You should override response(array $errors) method of FormRequest.
public function response(array $errors)
{
//Format your error message
if ($this->expectsJson()) {
return new JsonResponse($errors, 422);
}
return $this->redirector->to($this->getRedirectUrl())
->withInput($this->except($this->dontFlash))
->withErrors($errors, $this->errorBag);
}
I prefer the second option. We will be able to keep our controller clean that way, even when we use many validations for the data or using custom error message in the validation
I'm working on a fairly large JSON API using Slim3. My controllers/actions are currently littered with the following:
return $response->withJson([
'status' => 'error',
'data' => null,
'message' => 'Username or password was incorrect'
]);
At certain points in the application anything can go wrong and the response needs to be appropriate. But one thing that is common is the error responses are always the same. The status is always error, the data is optional (in the case of form validation errors data will contain those) and message is set to indicate to the user or consumer of the API what went wrong.
I smell code duplication. How can I reduce the code duplication?
From the top of my head all I could think of doing was creating a custom exception, something like App\Exceptions\AppException that takes option data and the message will be obtained form $e->getMessage().
<?php
namespace App\Exceptions;
class AppException extends Exception
{
private $data;
public function __construct($message, $data = null, $code = 0, $previous = null)
{
$this->data = $data;
parent::__construct($message, $code, $previous);
}
public function getData()
{
return $this->data;
}
}
Following that create middleware that calls $next wrapped in a try/catch:
$app->add(function($request, $response, $next) {
try {
return $next($request, $response);
}
catch(\App\Exceptions\AppException $e)
{
$container->Logger->addCritical('Application Error: ' . $e->getMessage());
return $response->withJson([
'status' => 'error',
'data' => $e->getData(),
'message' => $e->getMessage()
]);
}
catch(\Exception $e)
{
$container->Logger->addCritical('Unhandled Exception: ' . $e->getMessage());
$container->SMSService->send(getenv('ADMIN_MOBILE'), "Shit has hit the fan! Run to your computer and check the error logs. Beep. Boop.");
return $response->withJson([
'status' => 'error',
'data' => null,
'message' => 'It is not possible to perform this action right now'
]);
}
});
Now all I have to do at points in the code is to throw new \App\Exceptions\AppException("Username or password incorrect", null).
My only issue with this is it feels like I'm using exceptions for the wrong reasons and it may make debugging a little more difficult.
Any suggestions on reducing the duplicates and cleaning up error responses?
You can achieve similar similar results by creating an error handler which outputs JSON.
namespace Slim\Handlers;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
final class ApiError extends \Slim\Handlers\Error
{
public function __invoke(Request $request, Response $response, \Exception $exception)
{
$status = $exception->getCode() ?: 500;
$data = [
"status" => "error",
"message" => $exception->getMessage(),
];
$body = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
return $response
->withStatus($status)
->withHeader("Content-type", "application/json")
->write($body);
}
}
You must also configure Slim to use your custom error handler.
$container = $app->getContainer();
$container["errorHandler"] = function ($container) {
return new Slim\Handlers\ApiError;
};
Check Slim API Skeleton for example implemention.
I've been struggling with this for a while now.
Here's the code I've got.
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => 'required|max:100'
]);
if ($validator->fails()) {
//do something
}
}
The problem is that I get a FatalThrowableError right in my face with the following message:
Call to a member function parameter() on array
I can't find what I'm doing wrong. I'd appreciate some help here.
And also, I've had this validation before which worked:
$this->validate($request, [
'name' => 'required|unique:developers|max:100'
]);
But the thing with this one is, I had no idea how to catch when the validation failed. Is it possible to catch the validation fail when using it this way?
Using version: "laravel/lumen-framework": "5.2.*"
A FatalThrowableError exception is low level exception that is thrown typically by the symfony debug ErrorHandler. In lumen the queue worker, PhpEngine, console kernel and routing pipeline uses it as well.
Make sure of the following
That you have copied .env.example to .env
If you are using Facades, make sure that you enabled it inside bootstrap/app.php by uncommenting the line.
$app->withFacades();
Inside Lumen 5.2.8 either of the following would work.
The following will actually return a valid JSON object with the errors. You did not elaborate on your use case why that is not sufficient. What is nice with using the validate call like this is it actually returns a 422 http status code, which implies an unprocessed entity.
$app->get('/', function (Request $request) {
$this->validate($request, [
'name' => 'required'
]);
});
Using the facade works as well, albeit is returns a 200 status code.
$app->get('/', function (Request $request) {
$validator = Validator::make($request->only(['name']), [
'name' => 'required'
]);
if ($validator->fails()) {
return ['error' => 'Something went wrong'];
}
});
If you still do not come right with the Validator::make you can catch the default Validation exception using. It feels a little hacky.
$app->get('/', function (Request $request) {
try {
$this->validate($request, [
'name' => 'required'
]);
} catch (\Illuminate\Validation\ValidationException $e) {
// do whatever else you need todo for your use case
return ['error' => 'We caught the exception'];
}
});
I'm currently trying out on how to build a RESTful API with Laravel and I'm currently in the process of creating a new user. This is just a test and I'm getting some result when trying to validate the request using validation in Laravel; here is the result:
I've been trying to create a new one by this code:
public function store()
{
$validation = Validator::make(Request::all(),[
'username' => 'required|unique:users, username',
'password' => 'required',
]);
if($validation->fails()){
} else{
$createUser = User::create([
'username' => Request::get('username'),
'password' => Hash::make(Request::get('password'))
]);
}
}
but then I don't know how to return the error in validation. But it keeps on giving me that HTML as showed in the image when I was trying to do the if with validation->fails(). Is there a way to get the validation in JSON format?
these code will help you, working for me.
$response = array('response' => '', 'success'=>false);
$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) {
$response['response'] = $validator->messages();
} else {
//process the request
}
return $response;
You should probably return errors (which is an instance of Illuminate\Support\MessageBag) and encode that. A MessageBag instance allows you to convert it directly to its JSON representation.
$errors = $validation->errors();
return $errors->toJson();
Now not to toot my own horn but I've recently developed a RESTful API package for Laravel which does all of this for you and all you need to do is throw a simple exception. See my dingo/api package and the Wiki on returning errors. Basically, instead of returning the errors you would throw an exception.
throw new Dingo\Api\Exception\StoreResourceFailedException('Could not create a new user.', $validation->errors());
It would be represented by the following JSON.
{
"message": "Could not create a new user.",
"errors": {
"username": ["The username is already in use."]
}
}
Laravel provides out of the box a validation method that you can call from your Controller.
if you check the Laravel Controller abstract class you will find it uses a trait called ValidatesRequests
abstract class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}
So you can use a method $this->validate(Request $request, array $rules); as you long as your controller class extends the Controller
the full method declaration is
public function validate(Request $request, array $rules, array $messages = [], array $customAttributes = [])
{
$validator = $this->getValidationFactory()->make($request->all(), $rules, $messages, $customAttributes);
if ($validator->fails()) {
$this->formatValidationErrors($validator);
}
}
If The $validator fails, the method will throw an error depending on the request type, if it is ajax (in this case you should include in the request headers (Accept application/json) it will return a JSON response containing the validation errors.
For laravel 5.5 and up, see docs: AJAX Requests & Validation
TL;DR: On failed validation a json response with a 422 is returned along with the validation error messages. It took me a bit of time to find those validation errors in the response object, so to see the error messages if you're using axios, try this in your browser console:
axios.post('/api/your-route-here')
.then(response => {
console.log(response.data);
}).catch(error => {
console.log(error.response.data.errors)
});
There are many ways to get a validator response first is to get an all validation error at the same time i.e you will get a response like below
$validator = \Validator::make($request->all(), [
'username' => 'required|unique:users, username',
'password' => 'required',
]);
if ($validator->fails()) {
$responseArr = CustomHelper::returnRespArr("");
$responseArr['message'] = $validator->errors();;
$responseArr['token'] = '';
return response()->json($responseArr, Response::HTTP_BAD_REQUEST);
}
Response you will get is:
{
"status": false,
"data": [],
"message": {
"username": [
"The username field is required."
],
"password": [
"The password field is required."
]
},
"is_valid": 0,
"token": ""
}
The second way to get a validation response. In this, you will get a one validator error a time.
if ($validator->fails()) {
$responseArr = CustomHelper::returnRespArr("");
$responseArr['message'] = $validator->messages()->first();;
$responseArr['token'] = '';
return response()->json($responseArr,Response::HTTP_BAD_REQUEST);
}
The response you will get
{
"status": false,
"data": [],
"message": "The username field is required.",
"is_valid": 0,
"token": ""
}
I am using Laravel 9.x and found a quite simple way to validate errors with REST APIs:
public function store(Request $request)
{
$input = $request->all();
$validator = Validator::make($input, [
'title' => 'required|string|max:50'
]);
// Will return an error, if validation fails.
// https://laravel.com/api/9.x/Illuminate/Foundation/Validation/ValidatesRequests.html#method_validateWith
$this->validateWith($validator, $request);
// Only use the properties that were validated.
$input = $validator->validated();
// Create a new event model, with the data provided.
$event = Event::create($input);
return new EventResource($event);
}
In order to return a json error message, make sure to set the Accept header of the client to application/json. I make the mistake to not set this in my debug client, so I only saw html/xml messages.
You can also force the output to json.