如何在Laravel中将异常委托给全局异常?

时间:2019-04-25 18:48:30

标签: laravel laravel-5

控制器Laravel中有典型的代码:

public function create(CreateInvoiceRequest $request)
    {

        try {

            $invoice = Invoice::create(['']);

            return response()->json($model);

        } catch (\Exception $e) {
            return \Response::json(["errors" => $e->getMessage()], 400);
        }
    }

在异常情况下,我捕获并显示消息,如何在全局异常Laravel中对此进行滞后(移动)?我需要做这样的事情吗?

try { } } catch (\Exception $e) { throw new Exception($e); }

2 个答案:

答案 0 :(得分:2)

Laravel为此提供了一个很好的解决方案。在documentation中,我们被告知要在App\Exceptions\Handler中进行这种异常处理。

一个非常简单的示例如下:

// Your controller.

try {

    $invoice = Invoice::create(['']);

    return response()->json($model);

} catch (\Exception $e) {
    throw new CustomException('Invoice creation failed.');
}

// app\Exceptions\Handler.php

public function render($request, Exception $exception)
{
    if ($exception instanceof CustomException) {
        return response()->view('errors.custom', [], 500);
    }

    return parent::render($request, $exception);
}

我试图找出create是否会抛出特定异常。不幸的是我找不到这么快。如果是这种情况,您可以删除try catch,然后在render方法中监听此特定异常。

更新

(未经测试)

此外,您还可以覆盖save方法,以防止必须用trycatch包装(全部)数据库写入方法调用。

我们将需要一个BaseModel类:

<?php

namespace App\Models;

use App\Exceptions\ModelSaveException;
use Illuminate\Database\Eloquent\Model as EloquentModel;

class Model extends EloquentModel
{
    /**
     * Save the model to the database.
     *
     * @param  array  $options
     * @return bool
     * @throws \App\Exceptions\ModelSaveException
     */
    public function save(array $options = [])
    {
        try {
            return parent::save($options);
        } catch(\Exception $e) {
            throw new ModelSaveException($this);
        }
    }
}

如果没有try catch,您的控制器看起来会更干净:

$invoice = Invoice::create(['']);

return response()->json($model);

另外,我们可以检查模型是否由exists属性的制造商进行了更新。

<?php

namespace App\Exceptions;

class ModelSaveException extends \Exception
{
    /**
     * ModelSaveException constructor.
     *
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @return void
     */
     public function __construct($model)
     {
        if ($model->exists) {
            parent::__construct('Failed updating model.');
        } else {
            parent::__construct('Failed creating model.');
        }
     }
}

当然不要忘记从您新创建的模型中扩展:

use App\Models\Model;

class Invoice extends Model

答案 1 :(得分:1)

您可以创建一个自定义的可渲染异常。

try {
    // Your code...
} catch (\Exception $e) {
    throw new \App\Exceptions\CustomException('Your message');
}
  

您可以在自定义异常上直接定义报告和渲染方法,而不是在异常处理程序的报告和渲染方法中进行类型检查异常。这些方法存在时,框架将自动调用它们:

/**
 * Report the exception.
 *
 * @return void
 */
public function report()
{
    //
}

/**
 * Render the exception into an HTTP response.
 *
 * @param  \Illuminate\Http\Request
 * @return \Illuminate\Http\Response
 */
public function render($request)
{
    return response(...);
}

有关更多信息:https://laravel.com/docs/5.8/errors#renderable-exceptions