エラー処理

CodeIgniterは、SPLコレクションとフレームワークによって提供されるいくつかの例外の両方を含む、例外を通じてシステムにエラーレポートを組み込んでいます。

環境の設定によっては、エラーまたは例外が発生した場合のデフォルトの動作は、アプリケーションが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が定義したエラーメッセージを出力します。

上記の例では、あらゆる種類の例外をキャッチしています。UnknownFileExceptionのような特定の種類の例外のみを監視する場合は、catchパラメーターでそれを指定できます。スローされた他の例外で、キャッチされた例外の子クラスではないものは、エラーハンドラーに渡されます。

<?php

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

これは、自分でエラーを処理する場合や、スクリプトが終了する前にクリーンアップを実行する場合に便利です。エラーハンドラーを通常どおり機能させる場合は、catchブロック内で新しい例外をスローできます。

<?php

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

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

設定

エラーレポート

デフォルトでは、CodeIgniterはdevelopmenttesting環境ではすべてのエラーを含む詳細なエラーレポートを表示し、production環境ではエラーを表示しません。

../_images/error.png

CI_ENVIRONMENT変数を設定することで、環境を変更できます。環境の設定を参照してください。

重要

エラーレポートを無効にしても、エラーが発生した場合のログの書き込みは停止されません。

警告

.envファイルの設定は$_SERVER$_ENVに追加されることに注意してください。副作用として、詳細なエラーレポートが表示される場合、**安全な資格情報は公開されます**。

例外のログ記録

デフォルトでは、404 - ページが見つかりません例外以外のすべての例外がログに記録されます。これは、app/Config/Exceptions.php$log値を設定することでオンオフできます。

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

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

他のステータスコードのログ記録を無視するには、同じファイルで無視するステータスコードを設定できます。

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class Exceptions extends BaseConfig
{
    public $ignoredCodes = [404];
}

注記

現在のログ設定がすべての例外がログに記録される**クリティカル**エラーをログに記録するように設定されていない場合、例外のログ記録が行われない可能性があります。

フレームワーク例外

次のフレームワーク例外を使用できます。

PageNotFoundException

これは、404、ページが見つからないエラーをシグナルするために使用されます。スローされると、システムはapp/Views/errors/html/error_404.phpにあるビューを表示します。サイトのすべてのエラービューをカスタマイズする必要があります。app/Config/Routes.phpで404オーバーライドを指定した場合は、標準の404ページの代わりにそれが呼び出されます。

<?php

if (! $page = $pageModel->find($id)) {
    throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
}

404ページのデフォルトメッセージの代わりに表示されるメッセージを例外に渡すことができます。

ConfigException

この例外は、設定クラスの値が無効である場合、または設定クラスが正しい型ではない場合などに使用してください。

<?php

throw new \CodeIgniter\Exceptions\ConfigException();

これは、3の終了コードを提供します。

DatabaseException

この例外は、データベース接続を作成できない場合、または一時的に接続が失われた場合など、データベースエラーが発生した場合にスローされます。

<?php

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

これは、8の終了コードを提供します。

RedirectException

注記

v4.4.0以降、RedirectExceptionの名前空間が変更されました。以前はCodeIgniter\Router\Exceptions\RedirectExceptionでした。以前のクラスは非推奨です。

この例外は、他のすべてのレスポンスルーティングをオーバーライドし、特定の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 = \Config\Services::response()
    ->redirect('https://example.com/path')
    ->setHeader('Some', 'header')
    ->setCookie('and', 'cookie');

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

例外でHTTPステータスコードを指定する

バージョン4.3.0の新機能。

v4.3.0以降、例外クラスにHTTPExceptionInterfaceを実装することで、HTTPステータスコードを指定できます。

HTTPExceptionInterfaceを実装した例外がCodeIgniterの例外ハンドラによってキャッチされると、例外コードがHTTPステータスコードになります。

例外で終了コードを指定する

バージョン4.3.0の新機能。

v4.3.0以降、例外クラスにHasExitCodeInterfaceを実装することで、終了コードを指定できます。

HasExitCodeInterfaceを実装した例外がCodeIgniterの例外ハンドラによってキャッチされると、getExitCode()メソッドから返されたコードが終了コードになります。

非推奨警告のログ記録

バージョン4.3.0の新機能。

デフォルトでは、error_reporting()によって報告されたすべてのエラーはErrorExceptionオブジェクトとしてスローされます。これにはE_DEPRECATEDE_USER_DEPRECATEDエラーの両方が含まれます。PHP 8.1以降の使用の増加に伴い、多くのユーザーは内部関数のnull許容でない引数にnullを渡すことで例外がスローされるのを目にします。PHP 8.1への移行を容易にするために、CodeIgniterに非推奨をスローする代わりにログに記録するように指示できます。

まず、Config\Exceptionsのコピーが2つの新しいプロパティで更新され、次のように設定されていることを確認します。

<?php

namespace Config;

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

class Exceptions extends BaseConfig
{
    // ... other properties

    public bool $logDeprecations       = true;
    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
{
    // .. other properties

    public $threshold = 5; // originally 4 but changed to 5 to log the warnings from the deprecations
}

その後、それ以降の非推奨はスローされる代わりにログに記録されます。

この機能は、ユーザーによる非推奨についても機能します。

<?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環境変数を真の値に設定することで、これを設定できます。

カスタム例外ハンドラ

バージョン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);
    }
}

アプリケーションに必要な任意のロジックを使用して、例外を処理する必要があるかどうかを判断できますが、最も一般的な2つの方法は、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);
    }
}