如何从Laravel控制器返回AJAX错误?

gre*_*600 14 laravel laravel-5 laravel-5.2

我正在使用Laravel 5构建REST API.

在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'
        ];
    }
}
Run Code Online (Sandbox Code Playgroud)

如果客户端通过AJAX请求加载相应的路由,并BookStoreRequest发现请求不满足规则,它将自动将错误作为JSON对象返回.例如:

{
  "title": [
    "The title field is required."
  ]
}
Run Code Online (Sandbox Code Playgroud)

但是,该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 );

    }

}
Run Code Online (Sandbox Code Playgroud)

显然,我可以die(),但这太丑了.我宁愿以与验证错误相同的格式返回我的错误消息.像这样:

{
  "myErrorKey": [
    "A filesystem error occurred on the server. Please contact your administrator."
  ]
}
Run Code Online (Sandbox Code Playgroud)

我可以构造自己的JSON对象并返回它 - 但是Laravel当然支持这个.

什么是最好/最干净的方法?或者是否有更好的方法从Laravel REST API返回运行时(而不是验证时间)错误?

Jil*_*mas 21

您可以在json响应中设置状态代码,如下所示:

return Response::json(['error' => 'Error msg'], 404); // Status code here
Run Code Online (Sandbox Code Playgroud)

或者只是使用辅助函数:

return response()->json(['error' => 'Error msg'], 404); // Status code here
Run Code Online (Sandbox Code Playgroud)


Blu*_*nie 6

你可以通过很多方式做到这一点.

首先,您可以response()->json()通过提供状态代码来使用简单:

return response()->json( /** response **/, 401 );
Run Code Online (Sandbox Code Playgroud)

或者,以更复杂的方式确保每个错误都是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's 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这将返回应用程序中抛出的任何异常的json.现在,我们创建MyCustomException,例如在app/Exceptions中:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我们现在可以使用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 );

}
Run Code Online (Sandbox Code Playgroud)

现在,不仅抛出的异常MyCustomException将返回一个json错误,而是一般抛出的任何其他异常.