CodeIgniter3で本番環境時にエラーが発生した時にメールを送るようにする
今回は、CodeIgniter3で本番環境時にエラーが発生した時に、自身のメールアドレスに下記のような内容のメールを送れるようにしたので、やり方を紹介していく。
DATE: 2020/02/26 17:29:55
MESSAGE: syntax error, unexpected '$data' (T_VARIABLE)
FILEPATH: /var/www/html/application/controllers/AdminController.php
LINE: 22
環境
- CodeIgniter 3.1.6
- PHP 7.4.1
- Apache 2.4.6 (本番)
- CentOS 7 (本番)
エラー発生時にメールを送るようにする方法
エラー発生時にメールを送れるようにするために、今回は、CodeIginterのCore部分で定義されているset_error_handler
とset_exception_handler
を上書きする方法を採用した。
ただCore部分をいじるのは不味いので、Hooks(フック――フレームワークコアの拡張 — CodeIgniter 3.2.0-dev ドキュメント)を使うことで、エラーハンドリングを変えるようにする。
実装方法
1,Hooksクラスを作成する
まずはapplication/hooks
ディレクトリ内にErrorHandler.php
を作成して、そのファイルに下記のコードを書く。
<?php
class ErrorHandler
{
public function set_error()
{
set_error_handler([$this, "_error_handler"]);
set_exception_handler([$this, "_exception_handler"]);
}
public function _error_handler($severity, $message, $filepath, $line)
{
if (((E_ERROR | E_PARSE | E_COMPILE_ERROR | E_CORE_ERROR | E_USER_ERROR) & $severity) === $severity)
$this->send_email($message, $filepath, $line);
// CodeIgniterのCore部分のerror_handlerをそのまま使う。
_error_handler($severity, $message, $filepath, $line);
}
public function _exception_handler($exception)
{
$this->send_email(
$exception->getMessage(),
$exception->getFile(),
$exception->getLine()
);
// CodeIgniterのCore部分の_exception_handlerをそのまま使う。
_exception_handler($exception);
}
public function send_email($message, $filepath, $line)
{
$subject = "【重要】エラー検知通知メール";
$date = date('Y/m/d H:i:s');
ob_start();
include VIEWPATH . "/errors/error_mail.php";
$mailbody = ob_get_contents();
ob_end_clean();
$from = "From:" . getenv("CI_EMAIL_SENDER");
mb_send_mail(getenv("CI_EMAIL_RECEIVER"), $subject, $mailbody, $from);
}
}
今回はメールを送る処理の後に、CodeIgniterのCore部分のエラーハンドリング関数を使うようにした。
当初はErrorHandler
クラスのメソッドは全てstaticにしようとしたけど、「CodeIgniter/Hooks.php at develop · bcit-ci/CodeIgniter」のHook処理を見てみると、一旦クラスをインスタンス化してメソッドを呼び出しているので、Hookクラスにstaticは使えないことが分かったので見送った。
2,エラーメールのviewを作成
今回はエラーメールのviewをapplication/views/errors/error_mail.php
を作成した。
<?php
echo "DATE: " . $date . "\n";
echo "MESSAGE: " . $message . "\n";
echo "FILEPATH: " . $filepath . "\n";
echo "LINE: " . $line . "\n";
もっと良い処理がありそうだけど、今回はこれでいく。
3, Hookの設定をする
application/config/config.php
に行き、以下の設定をTRUE
に変更し、Hook処理ができるようにする。
$config['enable_hooks'] = TRUE;
そしてappplication/config/hooks.php
に行き、以下のコードを追加する。
<?php
$hook['pre_system'] = array(
'class' => 'ErrorHandler',
'function' => 'set_error',
'filename' => 'ErrorHandler.php',
'filepath' => 'hooks',
);
今回はpre_system
にHookを追加した。pre_systemにHookを追加することで、ルーティングが行われる前にHook処理を行ってくれる。
pre_system システム実行中の非常に早い段階で呼び出されます。ベンチマーククラスと フッククラスだけがこの時点でロードされています。ルーティングや 他のプロセスは実行されていません。 参考: フック――フレームワークコアの拡張 — CodeIgniter 3.2.0-dev ドキュメント
filepathをhooks
とすることで、application/hooks
ディレクトリ内にあるErrorHandler.php
を読み込むようになり、Hook処理時に下記のような処理を行ってくれるようになる。
$hook = new ErrorHandler();
$hook->set_error();