I'm not getting the response I expect.
This is the controller code for a Location web-service request:
<?php
namespace App\Http\Controllers;
use App\Location;
use Illuminate\Http\Request;
class LocationController extends Controller
{
/**
* Action method to add a location with the supplied Data
*
* @param \Illuminate\Http\Request $p_oRequest Request
*
* @return JSON
*/
public function add(Request $p_oRequest)
{
try {
$p_oRequest->validate(
array(
'name' => 'required|alpha_num',
'user_id' => 'required|integer',
),
array(
'name.required' => 'Name is required',
'name.string' => 'Name must be alphanumeric',
'user_id.required' => 'Curator User Id is required',
'user_id.required' => 'Curator User Id must be an integer',
)
);
} catch (\Exception $ex) {
$arrResponse = array(
'result' => 0,
'reason' => $ex->getMessage(),
'data' => array(),
'statusCode' => 404
);
} finally {
return response()->json($arrResponse);
}
}
}
The request is http://mydomain/index.php/api/v1/location/add?name=@!^
The response reason I expect is: { "result": 0, "reason": "Name must be alphanumeric", "data": [], "statusCode": 404 }
The actual response I get instead is: { "result": 0, "reason": "The given data was invalid.", "data": [], "statusCode": 404 }
Please help. This is bugging me.
I've finally discovered why this isn't working. It's not an issue of errors in the implementing code or Laravel, but one of either: (i). writing good PHP code to handle the self-evident result, which clearly I didn't do; (ii). insufficient documentation within Laravel on how to actually use the validation error response. Take your pick.
Laravel's validation throws a Illuminate\Validation\ValidationError. Believe it or not, this actually defaults the error message to "The given data was invalid.", so when you catch an \Exception and retrieve its $e->getMessage(), this default error-message is what you (correctly) get.
What you need to do is capture the \Illuminate\Validation\ValidationError - which I should've done originally, duh! - and then use its methods to help you distill the error messages from it.
Here's the solution I've come up with:
<?php
namespace App\Http\Controllers;
use App\Location;
use Illuminate\Http\Request;
class LocationController extends Controller
{
/**
* Action method to add a location with the supplied Data
*
* @param \Illuminate\Http\Request $p_oRequest Request
*
* @return JSON
*/
public function add(Request $p_oRequest)
{
try {
$arrValid = array(
'name' => 'required|alpha_num',
'user_id' => 'required|integer',
);
$p_oRequest->validate(
$arrValid,
array(
'name.required' => 'Name is missing',
'name.alpha_num' => 'Name must be alphanumeric',
'user_id.required' => 'User Id is missing',
'user_id.integer' => 'User Id must be an integer',
)
);
} catch (\Illuminate\Validation\ValidationException $e ) {
/**
* Validation failed
* Tell the end-user why
*/
$arrError = $e->errors(); // Useful method - thank you Laravel
/**
* Compile a string of error-messages
*/
foreach ($arrValid as $key=>$value ) {
$arrImplode[] = implode( ', ', $arrError[$key] );
}
$message = implode(', ', $arrImplode);
/**
* Populate the respose array for the JSON
*/
$arrResponse = array(
'result' => 0,
'reason' => $message,
'data' => array(),
'statusCode' => $e->status,
);
} catch (\Exception $ex) {
$arrResponse = array(
'result' => 0,
'reason' => $ex->getMessage(),
'data' => array(),
'statusCode' => 404
);
} finally {
return response()->json($arrResponse);
}
}
}
So, indeed, Laravel was supplying the correct response, and did what it said on the side of the tin, but I wasn't applying it correctly. Regardless, as a help to future me and other lost PHP-mariners at Laravel-sea, I provide the solution.
In addition, thanks to Marcin for pointing out my buggy coding, which would've caused a problem even if I had implemented the above solution.
I've only just seen this but all you need to do is move the validate call before the try/catch
$p_oRequest->validate(
[
'name' => 'required|alpha_num',
'user_id' => 'required|integer',
],
[
'name.required' => 'Name is required',
'name.string' => 'Name must be alphanumeric',
'user_id.required' => 'Curator User Id is required',
'user_id.required' => 'Curator User Id must be an integer',
]
);
try {
...
} catch(\Exception $e) {
return back()->withErrors($e->getMessage())->withInput();
}
Because Laravel catches the validation exception automatically and returns you back with old input and an array of errors which you can output like
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With