오류 처리

CodeIgniter는 SPL collection 예외와 프레임워크에서 제공하는 몇 가지 예외를 통해 시스템에 오류 보고를 구축합니다.

환경 설정에 따라 오류 또는 예외가 발생했을 때의 기본 작업은 응용 프로그램이 production 환경에서 실행되지 않는 한 자세한 오류 보고서를 표시하는 것입니다. production 환경에서는 사용자에게 최상의 사용자 경험을 유지하기 위해 보다 일반적인 메시지가 표시됩니다.

예외 사용

이 섹션은 초보 프로그래머나 예외 사용 경험이 없는 개발자를 위한 빠른 개요입니다.

예외란 무엇입니까?

예외는 단순히 예외가 “발생”할 때 발생하는 이벤트입니다. 그러면 스크립트의 현재 흐름이 중단되고 해당 오류 페이지를 표시하는 오류 처리기로 실행이 전송됩니다.

<?php

throw new \Exception('Some message goes here');

예외 잡기

예외를 발생시킬 수 있는 메서드를 호출하는 경우 try/catch 블록을 사용하여 해당 예외를 포착할 수 있습니다.

<?php

try {
    $user = $userModel->find($id);
} catch (\Exception $e) {
    exit($e->getMessage());
}

$userModel에서 예외가 발생하면 예외가 포착되고 catch 블록 내의 코드가 실행됩니다. 이 예에서는 스크립트가 종료되고 UserModel이 정의한 오류 메시지가 표시됩니다.

특정 예외 잡기

위의 예에서는 모든 유형의 예외를 포착합니다. DataException과 같은 특정 유형의 예외만 감시하려면 catch 매개변수에 이를 지정할 수 있습니다. 발생하고 포착된 예외의 하위 클래스가 아닌 다른 모든 예외는 오류 핸들러로 전달됩니다.

<?php

use CodeIgniter\Database\Exceptions\DataException;

try {
    $user = $userModel->find($id);
} catch (DataException $e) {
    // do something here...
}

이는 오류를 직접 처리하거나 스크립트가 끝나기 전에 정리를 수행하는 데 유용할 수 있습니다. 오류 처리기가 정상적으로 작동하도록 하려면 catch 블록 내에서 새 예외를 발생시킬 수 있습니다.

<?php

use CodeIgniter\Database\Exceptions\DataException;

try {
    $user = $userModel->find($id);
} catch (DataException $e) {
    // do something here...

    throw new \RuntimeException($e->getMessage(), $e->getCode(), $e);
}

설정

오류 보고

PHP ini 설정에서 display_errors이 활성화되면 CodeIgniter는 모든 오류와 함께 자세한 오류 보고서를 표시합니다.

따라서 기본적으로 CodeIgniter는 developmenttesting 환경에서 자세한 오류 보고서를 표시하고 production 환경에서는 오류를 표시하지 않습니다.

../_images/error.png

CI_ENVIRONMENT 변수를 설정하여 환경을 변경할 수 있습니다. 환경 설정을(를) 참조하세요.

중요

오류 보고를 비활성화해도 오류가 있는 경우 로그 기록이 중단되지 않습니다.

경고

.env 파일의 설정이 $_SERVER$_ENV에 추가됩니다. 부작용으로 이는 자세한 오류 보고서가 표시되면 your secure credentials are publicly exposed을 의미합니다.

로깅 예외

기본적으로 “404 - 페이지를 찾을 수 없음” 예외를 제외한 모든 예외가 기록됩니다. app/Config/Exceptions.php$log 값을 설정하여 이 기능을 켜고 끌 수 있습니다.

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class Exceptions extends BaseConfig
{
    // ...
    public bool $log = true;
    // ...
}

다른 상태 코드에 대한 로깅을 무시하려면 동일한 파일에서 상태 코드를 무시하도록 설정할 수 있습니다.

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class Exceptions extends BaseConfig
{
    // ...
    public array $ignoreCodes = [404];
    // ...
}

참고

현재 Log settings이 모든 예외가 기록되는 critical 오류를 기록하도록 설정되지 않은 경우 예외에 대한 기록이 여전히 발생하지 않을 수 있습니다.

지원 중단 경고 로깅

Added in version 4.3.0.

v4.3.0 이전에는 error_reporting()에서 보고된 모든 오류가 ErrorException 개체로 발생했습니다.

그러나 PHP 8.1+ 사용이 급증하면서 많은 사용자가 passing null to non-nullable arguments of internal functions에 대해 예외가 발생하는 것을 볼 수 있습니다.

v4.3.0부터 PHP 8.1로의 마이그레이션을 쉽게 하기 위해 CodeIgniter에는 사용 중단 오류(E_DEPRECATEDE_USER_DEPRECATED)만 예외로 발생시키지 않고 기록하는 기능이 있습니다.

기본적으로 CodeIgniter는 개발 환경에서 예외를 발생시키지 않고 지원 중단만 기록합니다. 프로덕션 환경에서는 로깅이 수행되지 않으며 예외가 발생하지 않습니다.

설정

이 기능에 대한 설정은 다음과 같습니다. 먼저 Config\Exceptions 복사본이 두 가지 새로운 속성으로 업데이트되고 다음과 같이 설정되었는지 확인하세요.

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;
use Psr\Log\LogLevel;

class Exceptions extends BaseConfig
{
    // ...
    public bool $logDeprecations = true; // If set to false, an exception will be thrown.
    // ...
    public string $deprecationLogLevel = LogLevel::WARNING; // This should be one of the log levels supported by PSR-3.
    // ...
}

다음으로, Config\Exceptions::$deprecationLogLevel에 설정한 로그 수준에 따라 Config\Logger::$threshold에 정의된 로거 임계값이 더 이상 사용되지 않는 로그 수준을 포함하는지 확인합니다. 그렇지 않은 경우 그에 따라 조정하십시오.

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class Logger extends BaseConfig
{
    // ...
    // This must contain the log level (5 for LogLevel::WARNING) corresponding to $deprecationLogLevel.
    public $threshold = (ENVIRONMENT === 'production') ? 4 : 9;
    // ...
}

그 이후에는 후속 지원 중단이 예외 없이 구성된 것으로 기록됩니다.

이 기능은 사용자 지원 중단에도 작동합니다.

<?php

@trigger_error('Do not use this class!', E_USER_DEPRECATED);
// Your logs should contain a record with a message like: "[DEPRECATED] Do not use this class!"

애플리케이션을 테스트하기 위해 항상 지원 중단을 적용할 수 있습니다. 환경 변수 CODEIGNITER_SCREAM_DEPRECATIONS을 진실한 값으로 설정하여 이를 구성할 수 있습니다.

프레임워크 예외

예외 디자인

v4.6.0부터 프레임워크가 발생하는 모든 예외 클래스는 다음과 같습니다.

  • CodeIgniter\Exceptions\ExceptionInterface 구현

  • CodeIgniter\Exceptions\LogicException 또는 CodeIgniter\Exceptions\RuntimeException 확장

참고

프레임워크는 위 종류의 예외 클래스만 발생시키지만, 사용되는 PHP 또는 기타 라이브러리는 다른 예외를 발생시킬 수 있습니다.

프레임워크에서 발생하는 두 가지 기본 예외 클래스가 있습니다.

논리예외

CodeIgniter\Exceptions\LogicException\LogicException을 확장합니다. 이 예외는 프로그램 논리의 오류를 나타냅니다. 이러한 종류의 예외는 코드 수정으로 직접 이어집니다.

런타임예외

CodeIgniter\Exceptions\RuntimeException\RuntimeException을 확장합니다. 런타임에서만 발견할 수 있는 오류가 발생하면 이 예외가 발생합니다.

다음 프레임워크 예외도 사용할 수 있습니다.

PageNotFound예외

이는 404, 페이지를 찾을 수 없음 오류를 알리는 데 사용됩니다.

<?php

use CodeIgniter\Exceptions\PageNotFoundException;

$page = $pageModel->find($id);

if ($page === null) {
    throw PageNotFoundException::forPageNotFound();
}

404 페이지의 기본 메시지 대신 표시될 예외에 메시지를 전달할 수 있습니다.

기본 404 보기 파일 위치는 HTTP 상태 코드 및 오류 보기을 참조하세요.

app/Config/Routing.php 또는 app/Config/Routes.php에서 404 오버라이드을 지정한 경우 표준 404 페이지 대신 호출됩니다.

구성 예외

이 예외는 구성 클래스의 값이 유효하지 않거나 구성 클래스가 올바른 유형이 아닌 경우 등에 사용해야 합니다.

<?php

throw new \CodeIgniter\Exceptions\ConfigException();

이는 종료 코드 3을 제공합니다.

데이터베이스예외

이 예외는 데이터베이스 연결을 생성할 수 없거나 일시적으로 끊어진 경우와 같은 데이터베이스 오류에 대해 발생합니다.

<?php

throw new \CodeIgniter\Database\Exceptions\DatabaseException();

이는 종료 코드 8을 제공합니다.

리디렉션예외

참고

v4.4.0부터 RedirectException의 네임스페이스가 변경되었습니다. 이전에는 CodeIgniter\Router\Exceptions\RedirectException이었습니다. v4.6.0에서는 이전 클래스가 제거되었습니다.

이 예외는 다른 모든 응답 라우팅을 무시하고 특정 URI로 강제로 리디렉션하는 것을 허용하는 특별한 경우입니다.

<?php

throw new \CodeIgniter\HTTP\Exceptions\RedirectException($uri);

$uri은 baseURL을 기준으로 한 URI 경로입니다. 기본값(302, “임시 리디렉션”) 대신 사용할 리디렉션 코드를 제공할 수도 있습니다.

<?php

throw new \CodeIgniter\HTTP\Exceptions\RedirectException($uri, 301);

또한 v4.4.0부터는 ResponseInterface를 구현하는 클래스의 객체를 첫 번째 인수로 사용할 수 있습니다. 이 솔루션은 응답에 추가 헤더나 쿠키를 추가해야 하는 경우에 적합합니다.

<?php

$response = service('response')
    ->redirect('https://example.com/path')
    ->setHeader('Some', 'header')
    ->setCookie('and', 'cookie');

throw new \CodeIgniter\HTTP\Exceptions\RedirectException($response);

예외에 HTTP 상태 코드 지정

Added in version 4.3.0.

v4.3.0부터 CodeIgniter\Exceptions\HTTPExceptionInterface을 구현하기 위해 Exception 클래스에 대한 HTTP 상태 코드를 지정할 수 있습니다.

HTTPExceptionInterface을 구현하는 예외가 CodeIgniter의 예외 핸들러에 의해 포착되면 예외 코드는 HTTP 상태 코드가 됩니다.

HTTP 상태 코드 및 오류 보기

예외 핸들러는 HTTP 상태 코드(있는 경우)에 해당하는 오류 보기를 표시합니다.

예를 들어 PageNotFoundExceptionHTTPExceptionInterface을 구현하므로 해당 예외 코드 404는 HTTP 상태 코드가 됩니다. 따라서 이 오류가 발생하면 시스템은 웹 요청일 때 app/Views/errors/html 폴더에 error_404.php을 표시합니다. CLI를 통해 호출되면 시스템은 app/Views/errors/cli 폴더에 error_404.php을 표시합니다.

HTTP 상태 코드에 해당하는 뷰 파일이 없으면 production.php 또는 error_exception.php이 표시됩니다.

참고

PHP ini 설정에서 display_errors이 켜져 있으면 error_exception.php이 선택되고 자세한 오류 보고서가 표시됩니다.

사이트의 app/Views/errors/html 폴더에 있는 모든 오류 보기를 사용자 정의해야 합니다.

특정 HTTP 상태 코드에 대한 오류 보기를 생성할 수도 있습니다. 예를 들어 “400 Bad Request”에 대한 오류 보기를 생성하려면 error_400.php을 추가합니다.

경고

해당 HTTP 상태 코드가 포함된 오류 보기 파일이 존재하는 경우 예외 처리기는 환경에 관계없이 해당 파일을 표시합니다. 뷰 파일은 프로덕션 환경에서 자체적으로 자세한 오류 메시지를 표시하지 않도록 구현해야 합니다.

예외에 종료 코드 지정

Added in version 4.3.0.

v4.3.0부터 CodeIgniter\Exceptions\HasExitCodeInterface을 구현하기 위해 Exception 클래스의 종료 코드를 지정할 수 있습니다.

HasExitCodeInterface을 구현하는 예외가 CodeIgniter의 예외 핸들러에 의해 포착되면 getExitCode() 메서드에서 반환된 코드가 종료 코드가 됩니다.

사용자 정의 예외 처리기

Added in version 4.4.0.

예외 표시 방법을 더 자세히 제어해야 하는 경우 이제 자체 처리기를 정의하고 적용 시기를 지정할 수 있습니다.

새 핸들러 정의

첫 번째 단계는 CodeIgniter\Debug\ExceptionHandlerInterface을 구현하는 새 클래스를 만드는 것입니다. CodeIgniter\Debug\BaseExceptionHandler을(를) 확장할 수도 있습니다. 이 클래스에는 기본 예외 처리기에서 사용되는 여러 유틸리티 메서드가 포함되어 있습니다. 새 핸들러는 단일 메소드인 handle()를 구현해야 합니다.

<?php

namespace App\Libraries;

use CodeIgniter\Debug\BaseExceptionHandler;
use CodeIgniter\Debug\ExceptionHandlerInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Throwable;

class MyExceptionHandler extends BaseExceptionHandler implements ExceptionHandlerInterface
{
    // You can override the view path.
    protected ?string $viewPath = APPPATH . 'Views/exception/';

    public function handle(
        Throwable $exception,
        RequestInterface $request,
        ResponseInterface $response,
        int $statusCode,
        int $exitCode,
    ): void {
        $this->render($exception, $statusCode, $this->viewPath . "error_{$statusCode}.php");

        exit($exitCode);
    }
}

이 예에서는 일반적으로 필요한 최소 코드 양을 정의합니다. 즉, 보기를 표시하고 적절한 종료 코드로 종료합니다. 그러나 BaseExceptionHandler은 다양한 다른 도우미 함수와 개체를 제공합니다.

새 처리기 구성

CodeIgniter에게 새 예외 처리기 클래스를 사용하도록 지시하는 것은 app/Config/Exceptions.php 구성 파일의 handler() 메서드에서 수행됩니다.

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Debug\ExceptionHandler;
use CodeIgniter\Debug\ExceptionHandlerInterface;
use Throwable;

class Exceptions extends BaseConfig
{
    // ...

    public function handler(int $statusCode, Throwable $exception): ExceptionHandlerInterface
    {
        return new ExceptionHandler($this);
    }
}

애플리케이션이 예외를 처리해야 하는지 여부를 결정하는 데 필요한 모든 논리를 사용할 수 있지만 가장 일반적인 두 가지 방법은 HTTP 상태 코드 또는 예외 유형을 확인하는 것입니다. 클래스가 이를 처리해야 하는 경우 해당 클래스의 새 인스턴스를 반환합니다.

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Debug\ExceptionHandlerInterface;
use CodeIgniter\Exceptions\PageNotFoundException;
use Throwable;

class Exceptions extends BaseConfig
{
    // ...

    public function handler(int $statusCode, Throwable $exception): ExceptionHandlerInterface
    {
        if (in_array($statusCode, [400, 404, 500], true)) {
            return new \App\Libraries\MyExceptionHandler($this);
        }

        if ($exception instanceof PageNotFoundException) {
            return new \App\Libraries\MyExceptionHandler($this);
        }

        return new \CodeIgniter\Debug\ExceptionHandler($this);
    }
}