
Користувацькі винятки в Laravel
27.02.2019 23:45 | 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();
}
}
В підсумку результат отримаємо такий же, але код набагато буде чистішим.
Успіхів!