Exceptions в Laravel

Отредачено 23.01.2025,
а чекнуто 644 💁

В 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 - как раз концептуальный пример того, что можно сделать в базовом исключении

 

ООП Laravel