Користувацькі винятки в Laravel

Користувацькі винятки в Laravel

Довелось зіткнутися з проектом на Laravel, у якому конструкції try catch зустрічались де тільки можливо, що, з моєї точки зору, в більшості випадків є не зовсім вірним рішенням. Це і стало приводом для даної невеликої статті.

Припустимо, є деякий клас ProductService з деяким методом doSomething, який може викинути виняток. У згаданому проекті виклик даного методу в контролері виглядав би приблизно так:

<?php

namespace App\Http\Controllers;

use App\Services\ProductService;

class ProductController extends Controller
{
    public function index()
    {
        try {
            (new ProductService)->doSomething();
        } catch (\Exception $e) {
            return response()->json([
                'message' => $e->getMessage()
            ]);
        }
    }
}

 

Для повноти картини клас ProductService:

<?php

namespace App\Services;

class ProductService
{
    public function doSomething()
    {
        // if something went wrong
        throw new \Exception('This is my custom exception');
    }
}

 

Суть в тому, що в подібних випадках немає ніякої потреби відловлювати винятки в контролері. Просто дайте винятку спливти і обробіть його в методі render класа Handler (app/Exceptions/Handler.php). А ще краще - створіть свій клас і пропишіть обробку в ньому. Пройдемося крок за кроком.

Створюємо клас винятку:

php artisan make:exception MyCustomException --render

 

Відкриваємо тільки що створений клас і доповнюємо код:

<?php

namespace App\Exceptions;

use Exception;

class MyCustomException extends Exception
{
    public function render($request)
    {
        return response()->json([
            'error' => $this->getMessage()
        ]);
    }
}

 

Примітка: якщо використовуєте sentry, можна додати метод report.

Далі підправимо ProductService:

<?php

namespace App\Services;

use App\Exceptions\MyCustomException;

class ProductService
{
    public function doSomething()
    {
        // if something went wrong
        throw new MyCustomException('This is my custom exception');
    }
}

 

І приберемо все зайве з контролера:

<?php

namespace App\Http\Controllers;

use App\Services\ProductService;

class ProductController extends Controller
{
    public function index()
    {
        (new ProductService)->doSomething();
    }
}

 

В підсумку результат отримаємо такий же, але код набагато буде чистішим.

Успіхів!