Exceptions в Laravel
В Laravel создание собственного класса исключения (Exception) позволяет вам обрабатывать ошибки в приложении более гибко и организованно. Вот шаги, чтобы создать и использовать собственный класс исключения:
Шаг 1: Создание класса исключения
Создайте новый файл для вашего класса исключения в каталоге app/Exceptions. Например, создадим исключение CustomException.php:
<?php
namespace App\Exceptions;
use Exception;
class CustomException extends Exception
{
// Можно добавить дополнительные свойства или методы
public function report()
{
// Логика для регистрации исключения
\Log::debug($this->getMessage());
}
public function render($request)
{
// Логика для ответа клиенту
return response()->json([
'error' => 'Custom error occurred.',
'message' => $this->getMessage()
], 400);
}
}
Шаг 2: Использование исключения в приложении
Теперь вы можете выбрасывать это исключение в любом месте вашего приложения, используя ключевое слово throw:
public function someMethod()
{
if ($someCondition) {
throw new \App\Exceptions\CustomException('Something went wrong!');
}
// Остальная логика метода
}
Шаг 3: Обработка исключения
Обработка исключений в Laravel обычно выполняется в классе Handler, который находится в app/Exceptions/Handler.php. Вы можете добавить логику обработки вашего исключения в метод render или report этого класса:
public function render($request, Exception $exception)
{
if ($exception instanceof \App\Exceptions\CustomException) {
return $exception->render($request);
}
return parent::render($request, $exception);
}
Шаг 4: Тестирование исключения
После того как вы создали исключение и добавили логику для его обработки, важно протестировать его, чтобы убедиться, что оно работает правильно. Вы можете создать тестовые случаи, используя PHPUnit, чтобы проверить, что исключение выбрасывается и обрабатывается, как ожидается.
Создание собственных классов исключений в Laravel обеспечивает более чистый и организованный способ обработки ошибок, позволяя вам лучше управлять различными типами исключений, которые могут возникнуть в вашем приложении.
PS
Спустя время использование exceptions переросло в нечто более удобное
Структура
Пример FileServiceBaseException
namespace App\Exceptions\FileService;
use App\Exceptions\BaseCustomException;
use Throwable;
class FileServiceBaseException extends BaseCustomException
{
public function __construct(string $message = 'Critical error', int $code = 500, ?Throwable $previous = null, string $clientMessage = 'Ошибка')
{
parent::__construct($message, $code, $previous, $clientMessage);
}
}
И сам BaseCustomException
namespace App\Exceptions;
use App\DTO\BoolDTO;
use App\DTO\DataTransferObject;
use App\DTO\Response;
use App\Helpers\GlobalHelper;
use Throwable;
class BaseCustomException extends \Exception
{
private string $clientMessage;
public function __construct(string $message = 'Critical error', int $code = 500, ?Throwable $previous = null, string $clientMessage = 'Ошибка')
{
parent::__construct($message, $code, $previous);
$this->clientMessage = $clientMessage;
$this->logException();
}
public function logException(): void
{
\Log::error(
GlobalHelper::getLogType(),
[
'data' => [
'log_type' => GlobalHelper::getLogType(),
'description' => $this->getMessage() . ' in ' . $this->getFile() . ' line ' . $this->getLine(),
'client_message' => $this->getClientMessage(),
],
]
);
}
public function answer(DataTransferObject $dto = new BoolDTO(false)): Response
{
return new Response($this->code, $this->getClientMessage(), $dto);
}
public function notifyAdmin()
{
// mail('', 'Error', $this->getMessage());//todo
}
public function getClientMessage(): string
{
return $this->clientMessage;
}
}
Есть пара моментов - clientMessage и метод answer - это часть структуры проекта, вся работа контроллеров вынесена в Library, контроллер только вызывает библу и передает данные, но ответ от библы всегда одного типа - Response, он принимает в себя ДТО, код ответа и сообщение которое будет передано клиенту (апи/вьюха - не важно)
notifyAdmin - как раз концептуальный пример того, что можно сделать в базовом исключении