38

私は特に「エラーロギング」を読んでいて、エラーロギングを処理するために使用するのに適したツールのように見える関数「error_log」を思いついた。しかし、それを使用するための最もスムーズで最良の方法はどのようになっていますか?

私が持っている場合

try {
     //try a database connection...

} catch (PDOException $e) {
    error_log($e->getMessage(), 3, "/var/tmp/my-errors.log");

}

これにより、エラーがmy-errors.logファイルに記録されます。しかし、ファイルがある場所、新しいフォルダーなどの位置を変更する必要がある場合はどうなりますか。大量のファイルがある場合は、それらすべてを変更する必要があります。

ここで、変数を使用してエラーログへのパスを設定することを考え始めました。確かにそれは機能する可能性がありますが、関数またはクラスメソッドでerror_logを使用したい場合はどうなりますか?次に、変数をグローバルとして設定する必要がありますが、それは悪い習慣と見なされます。しかし、クラスの奥深くで関数を使用するべきではない場合、それも悪い習慣と見なされませんか?ここで良い解決策は何ですか?

<?php

function legit() {
    try {
        if (1 == 1) {
            throw new Exception('There was an error here');
        }
    } catch (Exception $e) {
        throw new Exception('throw the error to the try-catch outside the function...');
    }

}

try {
    legit();
} catch (Exception $e) {
    echo 'error here' . $e->getMessage();

    //log it
}

これは私が上で話していたことの例です(クラス/関数の奥深くにロギングを持たない...それは良い方法ですか?)

これより先:

一般的に例外をどのように使用すべきかよくわかりません。メソッド内でSQLを使用してデータベースにINSERTを実行したい場合、try / catchを使用して、失敗した場合に例外を再スローしますか?それは良い習慣と考えられていますか?例をお願いします。

4

11 に答える 11

87

まず、PHP内の標準エラーメソッドを見てくださったことを称賛したいと思います。残念ながら、ご存知のとおりerror_log、いくつかの制限があります。

これは長い答えです。以下について調べるために読んでください。

  1. エラー
    • エラーを直接ログに記録するvstrigger_errorおよびset_error_handler
    • 良いエラーが悪くなるところ-致命的なエラー。
  2. 例外
    • SPL
    • それらをどうするか?
  3. コード
    • 設定
    • 使用法

TL;DRtrigger_errorエラーを発生させset_error_handlerてログに記録するために使用します。

1.エラー

プログラムで期待どおりに動作しない場合は、エラーを発生させて、誰かまたは何かに通知する必要があります。エラーは、プログラムが続行される可能性があるが、注目に値する、おそらく有害または誤った何かが発生した状況に対するものです。この時点で、多くの人は、選択したログパッケージを使用してエラーをすぐにログに記録したいと考えています。これはまったく間違ったことだと思います。trigger_errorで設定されたコールバックで処理できるように、を使用してエラーを発生させることをお勧めしますset_error_handler。これらのオプションを比較してみましょう。

エラーを直接ログに記録する

したがって、ロギングパッケージを選択しました。これで、コードでエラーが発生した場合はいつでも、呼び出しをロガーに拡散する準備が整いました。あなたが行うかもしれない単一の呼び出しを見てみましょう(私はジャックの答えのものと同様のロガーを使用します):

Logger::getLogger('standard')->error('Ouch, this hurts');

このコードを実行するには、何が必要ですか?

    クラス:ロガー
    メソッド:getLogger
    戻り値:メソッド「エラー」を持つオブジェクト

これらは、このコードを使用するために必要な依存関係です。このコードを再利用したい人は誰でも、これらの依存関係を提供する必要があります。これは、コードを再利用するには、標準のPHP構成ではもはや十分ではないことを意味します。最良の場合、依存性注入を使用すると、エラーを発行する可能性のあるすべてのコードにロガーオブジェクトを渡す必要があります。

また、コードが責任を負うものに加えて、エラーをログに記録する責任もあります。これは、単一責任の原則に反します。

エラーを直接ログに記録するのは悪いことがわかります。

救助へのtrigger_error

PHPにはtrigger_error、標準関数と同じようにエラーを発生させるために使用できるという関数があります。使用するエラーレベルは、エラーレベル定数で定義されます。ユーザーとして、ユーザーエラーの1つE_USER_ERRORE_USER_WARNINGまたはデフォルト値を使用する必要がありますE_USER_NOTICE(他のエラーレベルは標準機能などのために予約されています)。標準のPHP関数を使用してエラーを発生させると、標準のPHPインストールでコードを再利用できます。私たちのコードは、エラーをログに記録する責任を負いません(エラーが発生したことを確認するだけです)。

これを使用trigger_errorすると、エラーロギングプロセスの半分(エラーの発生)のみを実行し、次に説明するエラーハンドラーのエラーに対応する責任を回避できます。

エラーハンドラ

関数を使用してカスタムエラーハンドラーを設定しset_error_handlerます(コードのセットアップを参照)。このカスタムエラーハンドラーは、PHPの構成設定に応じて、通常はWebサーバーのエラーログにメッセージを記録する標準のPHPエラーハンドラーに代わるものです。falseカスタムエラーハンドラ内に戻ることで、この標準エラーハンドラを引き続き使用できます。

カスタムエラーハンドラには、エラーに応答するという単一の責任があります(実行するログを含む)。カスタムエラーハンドラー内では、システムへのフルアクセスが可能であり、必要なあらゆる種類のログを実行できます。事実上、オブザーバーデザインパターンを使用するすべてのロガーは問題ありません(二次的に重要であると信じているので、これについては説明しません)。これにより、新しいログオブザーバーをフックして、出力を必要な場所に送信できるようになります。

あなたはあなたのコードの単一の保守可能な部分のエラーであなたが好きなことをするための完全なコントロールを持っています。エラーログは、プロジェクト間で、または単一のプロジェクト内でページ間ですばやく簡単に変更できるようになりました。興味深いことに、抑制されたエラーでさえ、0@のカスタムエラーハンドラーに到達します。これは、マスクが尊重されている場合は報告されるべきではありません。errnoerror_reporting

良いエラーが悪くなるとき-致命的なエラー

特定のエラーから続行することはできません。次のエラーレベルはE_ERROR、カスタムエラーハンドラからは処理できません:、、、、、、。これらの種類のエラーが標準の関数呼び出しによってトリガーされると、カスタムエラーハンドラーはスキップされ、システムがシャットダウンします。これは、次の方法で生成できます。E_PARSEE_CORE_ERRORE_CORE_WARNINGE_COMPILE_ERRORE_COMPILE_WARNING

call_this_function_that_obviously_does_not_exist_or_was_misspelt();

これは重大な間違いです!から回復することは不可能であり、システムはシャットダウンしようとしています。私たちの唯一の選択はregister_shutdown_function、シャットダウンに対処することです。ただし、この関数は、スクリプトが完了するたびに実行されます(成功した場合と失敗した場合)。これを使用するとerror_get_last、最後のエラーが致命的なエラーであったときに、いくつかの基本情報をログに記録できます(この時点でシステムはほぼシャットダウンされます)。正しいステータスコードを送信し、選択した内部サーバーエラータイプのページを表示することも役立ちます。

2.例外

例外は、基本的なエラーと非常によく似た方法で処理できます。例外の代わりにtrigger_error、コードによってスローされます(手動で、throw new Exceptionまたは標準の関数呼び出しから)。で例外を処理するために使用するコールバックを定義するために使用set_exception_handlerします。

SPL

標準PHPライブラリ(SPL)は例外を提供します。trigger_errorこれらは、コードに余分な依存関係を導入しないPHPの標準部分であるため、例外を発生させるための私の好ましい方法です。

それらをどうするか?

例外がスローされた場合、次の3つの選択肢があります。

  1. それをキャッチして修正します(その後、コードは何も悪いことが起こらなかったかのように続行します)。
  2. それをキャッチし、有用な情報を追加して、それを再スローします。
  3. それをより高いレベルに泡立たせましょう。

スタックの各レベルで、これらの選択が行われます。最終的に、バブルが最高レベルに達すると、設定したコールバックset_exception_handlerが実行されます。catchこれは、コード内のステートメント全体に広がるのではなく、(エラー処理と同じ理由で)ロギングコードが属する場所です。

3.コード

設定

エラーハンドラ

function errorHandler($errno , $errstr, $errfile, $errline, $errcontext)
{
    // Perform your error handling here, respecting error_reporting() and
    // $errno.  This is where you can log the errors.  The choice of logger
    // that you use is based on your preference.  So long as it implements
    // the observer pattern you will be able to easily add logging for any
    // type of output you desire.
}

$previousErrorHandler = set_error_handler('errorHandler');

例外ハンドラ

function exceptionHandler($e)
{
    // Perform your exception handling here.
}

$previousExceptionHandler = set_exception_handler('exceptionHandler');

シャットダウン機能

function shutdownFunction()
{
    $err = error_get_last();

    if (!isset($err))
    {
        return;
    }

    $handledErrorTypes = array(
        E_USER_ERROR      => 'USER ERROR',
        E_ERROR           => 'ERROR',
        E_PARSE           => 'PARSE',
        E_CORE_ERROR      => 'CORE_ERROR',
        E_CORE_WARNING    => 'CORE_WARNING',
        E_COMPILE_ERROR   => 'COMPILE_ERROR',
        E_COMPILE_WARNING => 'COMPILE_WARNING');

    // If our last error wasn't fatal then this must be a normal shutdown.  
    if (!isset($handledErrorTypes[$err['type']]))
    {
        return;
    }

    if (!headers_sent())
    {
        header('HTTP/1.1 500 Internal Server Error');
    }

    // Perform simple logging here.
}

register_shutdown_function('shutdownFunction');

使用法

エラー

// Notices.
trigger_error('Disk space is below 20%.', E_USER_NOTICE);
trigger_error('Disk space is below 20%.'); // Defaults to E_USER_NOTICE

// Warnings.
fopen('BAD_ARGS'); // E_WARNING fopen() expects at least 2 parameters, 1 given
trigger_error('Warning, this mode could be dangerous', E_USER_WARNING);

// Fatal Errors.    
// This function has not been defined and so a fatal error is generated that
// does not reach the custom error handler.
this_function_has_not_been_defined();
// Execution does not reach this point.

// The following will be received by the custom error handler but is fatal.
trigger_error('Error in the code, cannot continue.', E_USER_ERROR);
// Execution does not reach this point.

例外

以前の3つの選択肢のそれぞれが、一般的な方法でここにリストされ、修正し、追加して、バブルさせます。

1修正可能:

try
{
    $value = code_that_can_generate_exception();
}
catch (Exception $e)
{
    // We decide to emit a notice here (a warning could also be used).
    trigger_error('We had to use the default value instead of ' .
                  'code_that_can_generate_exception\'s', E_USER_NOTICE);
    // Fix the exception.
    $value = DEFAULT_VALUE;
}

// Code continues executing happily here.

2追加:

code_that_can_generate_exception()がについて知らない方法を以下で確認して$contextください。このレベルのcatchブロックには、再スローすることで役立つ場合に例外に追加できる詳細情報があります。

try
{
    $context = 'foo';
    $value = code_that_can_generate_exception();
}
catch (Exception $e)
{
    // Raise another exception, with extra information and the existing
    // exception set as the previous exception. 
    throw new Exception('Context: ' . $context, 0, $e);
}

3それを泡立たせます:

// Don't catch it.
于 2012-05-10T16:57:54.720 に答える
37

この回答をより多くの聴衆に適用できるようにすることが求められているので、ここに行きます。

前文

通常、エラー処理は、アプリケーションを作成するときに最初に考えたいことではありません。間接的な結果として、必要に応じてボルトで固定されます。ただし、PHPの既存のメカニズムを活用するために多くの費用をかける必要はありません。

これはかなり長い記事なので、論理的なテキストのセットに分解しました。

エラーのトリガー

PHP内では、エラーがトリガーされる2つの異なる方法があります。

  1. PHP自体(未定義の変数の使用など)または内部関数(imagecreatefromjpegファイルを開くことができなかったなど)からのエラー、
  2. trigger_error、を使用してユーザーコードによってトリガーされたエラー

これらは通常、ページに印刷されます(display_errorsスイッチがオフになってerror_reportingいるかゼロでない限り)。これは、私のような完璧なコードを記述しない限り、本番マシンの標準となるはずです...次に進みます)。set_error_handlerこれらのエラーもキャプチャできるため、後で説明するを使用して、コードの問題点を垣間見ることができます。

例外のスロー

例外は、主に次の3つの点でエラーとは異なります。

  1. それらを処理するコードは、それらがスローされた場所から遠く離れている可能性があります。オリジンの変数の状態は、明示的にExceptionコンストラクターに渡す必要があります。そうしないと、スタックトレースしかありません。
  2. 例外とキャッチの間のコードは完全にスキップされますが、エラーが発生した後(そしてそれは致命的ではありませんでした)、コードは続行されます。
  3. Exceptionそれらはメインクラスから拡張できます。これにより、特定の例外をキャッチして処理できますが、他のコードによってキャッチされるまで、他の人がスタックをバブルダウンすることができます。参照:http ://www.php.net/manual/en/language.exceptions.php

例外をスローする例については、後で説明します。

エラーの処理

エラーのキャプチャと処理は、エラーハンドラを登録することで非常に簡単です。例:

function my_error_handler($errno, $errstr, $errfile = 'unknown', $errline = 0, array $errcontext = array())
{
    // $errcontext is very powerful, it gives you the variable state at the point of error; this can be a pretty big variable in certain cases, but it may be extremely valuable for debugging
    // if error_reporting() returns 0, it means the error control operator was used (@)
    printf("%s [%d] occurred in %s:%d\n%s\n", $errstr, $errno, $errfile, $errline, print_r($errcontext, true));

    // if necessary, you can retrieve the stack trace that led up to the error by calling debug_backtrace()

    // if you return false here, the standard PHP error reporting is performed
}

set_error_handler('my_error_handler');

キックの場合、次のエラーハンドラー(PHP> = 5.1)を登録することで、すべてのエラーをErrorException同様に変換できます。

function exception_error_handler($errno, $errstr, $errfile, $errline)
{
    throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}

set_error_handler("exception_error_handler");

例外の処理

ほとんどの場合、バックアップ計画を可能にする原因となったコードに可能な限り近い例外を処理します。たとえば、データベースレコードを挿入しようとすると、主キー制約の例外がスローされます。代わりにレコードを更新することで回復できます(ほとんどのデータベースがこれを自分で処理できるために考案されました)。一部の例外はローカルで処理できないため、カスケードダウンする必要があります。例:

function insertRecord($user, $name)
{
    try {
        if (true) {
            throw new Exception('This exception should not be handled here');
        }
        // this code is not executed
        $this->db->insert('users', array('uid' => $user, 'name' => $name));
    } catch (PDOException $e) {
        // attempt to fix; an exception thrown here will cascade down
        throw $e; // rethrow exception

        // since PHP 5.3.0 you can also nest exceptions
        throw new Exception("Could not insert '$name'", -1, $e);
    } catch (WhatEverException $e) {
        // guess what, we can handle whatever too
    }
}

滑りやすい例外

では、どこでも例外をキャッチしないとどうなりますか?を使用してそれをキャッチすることもできますset_exception_handler

function my_exception_handler(Exception $exception)
{
    // do your stuff here, just don't throw another exception here
}

set_exception_handler('my_exception_handler');

コード内のどこかに例外を処理する意味のある方法がない限り、これは推奨されません。

エラー/例外のログ

エラーを処理しているので、どこかにログを記録する必要があります。私の例では、ApacheがJavaからPHPに移植したLOG4PHPというプロジェクトを使用しています。他にもありますが、それは柔軟なロギング機能の重要性を示しています。

次の概念を使用します。

  1. ロガー-ユーザーに代わってロギングを実行する名前付きエンティティ。プロジェクト内のクラスに固有にすることも、共通のロガーとして共有することもできます。
  2. アペンダー-各ログ要求は、事前定義された条件(ログレベルなど)に基づいて、1つ以上の宛先(電子メール、データベース、テキストファイル)に送信できます。
  3. レベル-ログは、デバッグメッセージから致命的なエラーに分類されます。

さまざまなメッセージレベルを説明するための基本的な使用法:

Logger::getLogger('main')->info('We have lift off');
Logger::getLogger('main')->warn('Rocket is a bit hot');
Logger::getLogger('main')->error('Houston, we have a problem');

これらの概念を使用すると、非常に強力なロギング機能をモデル化できます。たとえば、上記のコードを変更せずに、次の設定を実装できます。

  1. 開発者が確認できるように、すべてのデバッグメッセージをデータベースに収集します。本番サーバーでこれを無効にすることができます。
  2. 一日の終わりにメールで送信する可能性のある毎日のファイルに警告を収集します。
  3. 致命的なエラーについてすぐにメールを送信します。
于 2012-05-07T04:20:20.210 に答える
3

それを定義し、それを使用します:)

define('ERRORLOG_PATH', '/var/tmp/my-errors.log');

error_log($e->getMessage(), 3, ERRORLOG_PATH);

または、の3番目のパラメーターをerror_logオプションにして、デフォルトで目的のパスにします。

于 2012-04-26T12:02:42.313 に答える
3

それでもログを処理するカスタムの方法が必要な場合(つまり、標準を使用したくない場合trigger_error())は、Zend_Log(http://framework.zend.com/manual/en/zend.log.overview)を参照することをお勧めします。 html)これらの理由で:

  1. これはスタンドアロンコンポーネントとして使用できます。ZFはフルスタックフレームワークではありません。Zend_LoaderおよびZend_Log名前空間のみをコピーし、Zend_Loaderをインスタンス化して使用できます。下記参照:

    require_once('Zend/Loader/Autoloader.php');
    
    $loader = Zend_Loader_Autoloader::getInstance();
    
    $logger = new Zend_Log();    
    $writer = new Zend_Log_Writer_Stream('php://output');
    
    $logger->addWriter($writer);    
    $logger->log('Informational message', Zend_Log::INFO);
    
  2. 多くのロギングライブラリが提供されましたが、Zendチーム(PHP langの創設者)はそれらが何をするかを知っていると思います

  3. 任意のライターを使用できます(データベース、STDOUT-上記を参照、ファイルなど、独自に作成してログメッセージをWebサービスに投稿することもできます)
  4. ログレベル
  5. ログの形式を変更する可能性があります(ただし、すぐに使用できる形式は私の心にぴったりです)。上記の標準フォーマッタを使用した例では、次のようなものが生成されます。

2012-05-07T23:57:23 + 03:00情報(6):情報メッセージ

  1. 参照を読むだけで、phpエラーをキャッチするように構成されている可能性があります
于 2012-05-07T21:02:14.800 に答える
3

さらに、エラーロギング(そして実際にはすべてのロギング)には、symfonyフレームワークと同じようにイベントディスパッチャーを使用します。

このsfコンポーネントを見てください(非常に軽量な依存関係であり、フレームワーク全体は必要ありません。おそらく3つの関連するphpクラスと2つのインターフェイスがあります)

https://github.com/symfony/EventDispatcher

このようにして、アプリケーションのブートストラップのどこかにディスパッチャーを作成できます。

use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\Event;

$dispatcher = new EventDispatcher();

//register listeners
$dispatcher->addListener('application.log', function (Event $event) {
    //do anything you want
});

次に、次のような方法で、コードの任意の場所でイベントを発生させることができます。

$dispatcher->dispatch(new GenericEvent('application.log', array('message' => 'some log', 'priority' => 'high'));

もちろん、独自のイベントでイベントクラスをサブクラス化できます。

class LogEvent extends GenericEvent {
    public function __construct($message, $priority = 'INFO') {
        parent::__construct('application.log', array('message'=>$message,'priority'=>$priority));
    }
    public function getMessage() { return $this->getArgument('message'); }
    public function getPriority() { return $this->getArgument('priority'); }
}

// now raising LogEvent is much cleaner:
$dispatcher->dispatch(new LogEvent('some log'));

これにより、ExceptionEventなどのよりカスタマイズされたイベントを作成することもできます。

 class ExceptionEvent extends GenericEvent {
    public function __construct(Exception $cause) {
        parent::__construct('exception.event', array('cause' => $cause));
    }
 }

そしてそれに応じてそれらを処理します。

利点

  • ロギングロジックをアプリケーションから分離します
  • 実行時にロガーを簡単に追加および削除できます
  • 必要な数のロガーを簡単に登録できます(つまり、すべてをテキストファイルに記録するDebugLogger、エラーのみをerror_logに記録するErrorLogger、本番環境で重大なエラーのみを記録して管理者に電子メールで送信するCriticalLoggerなど)。
  • ロギングだけでなく、イベントディスパッチャーを使用できます(実際、オブザーバーパターンが適切なすべてのジョブに対して)
  • 実際のロガーは「実装の詳細」にすぎません。簡単に置き換えることができるため、ログの場所は関係ありません。メソッドの名前をリファクタリングしたり、何かを変更したりすることなく、いつでもログの宛先を置き換えることができます。コードで。
  • 複雑なログルーティングロジックを実装したり、ログ形式をグローバルに変更したりするのは簡単です(ロガーを構成することにより)
  • リスナー(ロガー)とディスパッチャー(ログイベントを通知するクラスへの)の両方に依存性注入を使用すると、すべてがさらに柔軟になります

実際のロギング

誰かがすでに述べたように、Monolog、Zend_Log、log4phpなどのすぐに使えるライブラリを使用することをお勧めします。これらを手動でコーディングする理由はおそらくありません(そして、最後に必要なのは壊れたエラーロガーです) !)

PS:コードスニペットを擬似コードとして扱います。私はそれらをテストしませんでした。詳細は、言及されたライブラリのドキュメントに記載されています。

于 2012-05-11T09:06:46.250 に答える
0

エラーを処理するPHPの方法が十分に柔軟でない場合(たとえば、データベースにログを記録したい場合、ファイルにログを記録したい場合など)、カスタムPHPログフレームワークを使用/作成する必要があります。

https://stackoverflow.com/questions/341154/php-logging-frameworkのディスカッションを参照するか、最高の選択肢であるKLoggerを試してみてください。ただし、ロギングのカスタム宛先をサポートしているかどうかはわかりません。しかし、少なくとも、それは小さくて読みやすいクラスであり、あなた自身のニーズに合わせてさらに拡張できるはずです。

于 2012-05-01T07:31:57.457 に答える
0

私はTomVandder Woerdtのロギングソリューションを使用します。これは、要件に対して最も単純で最も効果的です。

他の質問について:

解決策がある特定の種類の例外がない限り、関数内で例外をキャッチ/再スローする必要はありません。

やや単純な例:

define('ERRORLOG_PATH', '/var/tmp/my-errors.log');
function do_something($in)
{
    if (is_good($in))
    {
        try {
            return get_data($in);
        } catch (NoDataException $e) {
            // Since it's not too big a deal that nothing
            // was found, we just return false.
            return false;
        }
    } else {
        throw new InvalidArguementException('$in is not good');
    }
}

function get_data($data)
{
    if (!is_int($data))
    {
        InvalidArguementException('No');
    }
    $get = //do some getting.
    if (!$get)
    {
        throw new NoDataException('No data was found.');
    } else {
        return $get;
    }
}

try {
   do_something('value');
} catch (Exception $e) {
   error_log($e->getMessage(), 3, ERRORLOG_PATH);
   die ('Something went wrong :(');
}

ここではNoDataException、それを整理する他のロジックがあるため、キャッチするだけです。他のすべてのエラーは最初のキャッチに分類され、上位のキャッチによって処理されます。これは、スローされたすべての例外が、階層内のある時点でから継承する必要があるためExceptionです。

Exception明らかに、 (イニシャルの外側try {}または上部に)もう一度スローするcatch {}と、スクリプトはUncaught Exceptionエラーで終了し、エラーログは失われます。

ずっと行きたい場合は、を使用してカスタムエラー処理関数を実装しset_error_handler()、そこにロギングを配置することもできます。

于 2012-05-09T10:52:56.070 に答える
0

満たすべき2つの課題があります。1つは、さまざまなチャネルへのロギングを柔軟に行うことです。この場合、たとえばMonologを確認する必要があります。

2番目の課題は、そのログインをアプリケーションに組み込むことです。私見の最良のケースは、ロギングを明示的に使用しないことです。ここでは、たとえばアスペクト指向が便利です。良いサンプルはflow3です。

しかし、これは問題に対する鳥瞰図です...

于 2012-05-10T08:50:40.047 に答える
0

2番目のパラメータを設定または変更することで複数の種類のログファイルを書き込むことができる独自の関数を使用しています。

開発プロジェクトの「ネイティブ」と見なす関数のライブラリにlog関数を含めることで、「正しい方法は何か」についてあなたが尋ねている概念的な質問を乗り越えます。date()そうすれば、これらの関数は、またはのような「MY」phpコアの一部であると見なすことができます。time()

この基本バージョンのdlogでは、配列も処理します。私はもともとこれをエラーのログに使用していましたが、コードが特定のセクションに入った時刻のログ記録やユーザーのログインなど、他の「迅速で汚い」短期追跡に使用することになりました。

function dlog($message,$type="php-dlog")
{
    if(!is_array($message)  )
        $message=trim($message);
    error_log(date("m/d/Y h:i:s").":".print_r($message,true)."\n",3, "/data/web/logs/$_SERVER[HTTP_HOST]-$type.log");
} 
于 2012-05-11T03:36:44.360 に答える
0

ほとんどのエラーロガーと例外ロガーは、ログファイルにアクセスできないため、ほとんどの人にとって役に立たないものです。

私はカスタムエラーハンドラーとカスタム例外ハンドラーを使用することを好み、システムがデータベースで実行されている場合は、本番環境でエラーをデータベースに直接記録します。

開発中、display_errorsが設定されている場合、ブラウザですべてのエラーが発生するため、何もログに記録されません。

また、補足として、カスタムエラーハンドラーに例外をスローさせないでください。それは本当に悪い考えです。バッファハンドラと一部の拡張機能にバグが発生する可能性があります。また、fopen()などの一部のコアPHP関数は、失敗時に警告または通知を発生させます。これらはそれに応じて処理する必要があり、例外が発生した場合にアプリケーションを停止しないでください。

PHPのドキュメントでエラーハンドラが例外をスローすることに言及しているのは、メモのバグです。

于 2013-04-08T05:38:50.927 に答える
0

KNLが述べているように、これは非常に正しいですが、残念ながらまだドキュメント化されていません。例外をスローするエラーがあることは、PHP開発者が推奨するものではなく、誰かがドキュメントに誤りを犯しました。それは確かに多くの拡張機能でバグを引き起こす可能性があるので、それをしないでください。

これは、ircの#PHPですでに議論されています。

「ただし、エラーはErrorExceptionを使用して例外に単純に変換できます。」http://php.net/manual/en/language.exceptions.phpで削除される予定です。

于 2013-04-17T02:14:49.600 に答える