Как вернуть ошибки AJAX с контроллера Laravel?
Я создаю REST API с Laravel 5.
В Laravel 5 вы можете подклассом App\Http\Requests\Request
определить правила проверки, которые должны быть выполнены до того, как будет обработан конкретный маршрут. Например:
<?php
namespace App\Http\Requests;
use App\Http\Requests\Request;
class BookStoreRequest extends Request {
public function authorize() {
return true;
}
public function rules() {
return [
'title' => 'required',
'author_id' => 'required'
];
}
}
Если клиент загружает соответствующий маршрут через запрос AJAX, а BookStoreRequest
обнаруживает, что запрос не удовлетворяет правилам, он автоматически возвращает ошибку (-ы) как объект JSON. Например:
{
"title": [
"The title field is required."
]
}
Однако метод Request::rules()
может только проверять ввод, и даже если вход действителен, могут возникнуть другие виды ошибок после того, как запрос уже принят и передан контроллеру. Например, скажем, что контроллеру необходимо по какой-то причине записать новую информацию о книге в файл, но файл не может быть открыт:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Http\Requests\BookCreateRequest;
class BookController extends Controller {
public function store( BookStoreRequest $request ) {
$file = fopen( '/path/to/some/file.txt', 'a' );
// test to make sure we got a good file handle
if ( false === $file ) {
// HOW CAN I RETURN AN ERROR FROM HERE?
}
fwrite( $file, 'book info goes here' );
fclose( $file );
// inform the browser of success
return response()->json( true );
}
}
Очевидно, я мог бы просто die()
, но это супер уродливо. Я бы предпочел вернуть мое сообщение об ошибке в том же формате, что и ошибки проверки. Вот так:
{
"myErrorKey": [
"A filesystem error occurred on the server. Please contact your administrator."
]
}
Я мог бы создать свой собственный объект JSON и вернуть его, но, конечно же, Laravel поддерживает это.
Какой лучший/самый чистый способ сделать это? Или есть лучший способ вернуть ошибки времени выполнения (в отличие от проверки времени) из LARvel API REST?
Ответы
Ответ 1
Вы можете установить код состояния в ответе json, как показано ниже:
return Response::json(['error' => 'Error msg'], 404); // Status code here
Или просто используя вспомогательную функцию:
return response()->json(['error' => 'Error msg'], 404); // Status code here
Ответ 2
Вы можете сделать это разными способами.
Сначала вы можете использовать простой response()->json()
, указав код состояния:
return response()->json( /** response **/, 401 );
Или более сложным способом гарантировать, что каждая ошибка является ответом json, вы можете настроить обработчик исключений, чтобы поймать специальное исключение и вернуть json.
Откройте App\Exceptions\Handler
и выполните следующие действия:
class Handler extends ExceptionHandler
{
/**
* A list of the exception types that should not be reported.
*
* @var array
*/
protected $dontReport = [
HttpException::class,
HttpResponseException::class,
ModelNotFoundException::class,
NotFoundHttpException::class,
// Don't report MyCustomException, it only for returning son errors.
MyCustomException::class
];
public function render($request, Exception $e)
{
// This is a generic response. You can the check the logs for the exceptions
$code = 500;
$data = [
"error" => "We couldn't hadle this request. Please contact support."
];
if($e instanceof MyCustomException) {
$code = $e->getStatusCode();
$data = $e->getData();
}
return response()->json($data, $code);
}
}
Это приведет к возврату json для любого исключения, созданного в приложении.
Теперь мы создаем MyCustomException
, например, в приложении/Исключения:
class MyCustomException extends Exception {
protected $data;
protected $code;
public static function error($data, $code = 500)
{
$e = new self;
$e->setData($data);
$e->setStatusCode($code);
throw $e;
}
public function setStatusCode($code)
{
$this->code = $code;
}
public function setData($data)
{
$this->data = $data;
}
public function getStatusCode()
{
return $this->code;
}
public function getData()
{
return $this->data;
}
}
Теперь мы можем просто использовать MyCustomException
или любое исключение, расширяющее MyCustomException
, чтобы вернуть ошибку json.
public function store( BookStoreRequest $request ) {
$file = fopen( '/path/to/some/file.txt', 'a' );
// test to make sure we got a good file handle
if ( false === $file ) {
MyCustomException::error(['error' => 'could not open the file, check permissions.'], 403);
}
fwrite( $file, 'book info goes here' );
fclose( $file );
// inform the browser of success
return response()->json( true );
}
Теперь не только исключения, сброшенные через MyCustomException
, возвращают ошибку json, но и любое другое исключение, которое вообще генерируется.