Как делегировать исключение в глобальное исключение в Laravel? - PullRequest
0 голосов
/ 25 апреля 2019

В контроллере 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 ]

2 голосов
/ 25 апреля 2019

У Laravel есть хорошее решение для этого. В документации нам сказано сделать такое исключение при обработке в 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, чтобы избежать необходимости переносить (все) вызовы метода записи в базу данных с try и catch.

Нам понадобится 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 голос
/ 25 апреля 2019

Вы можете создать настраиваемое исключение для визуализации.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...