1

CodeIgniterを利用したWebサイトで、当惑するような問題が発生しました。1つのPHPクラス(TChild)は、断続的に「クラスを再宣言できません」エラーをスローし始め、それを使用するすべてのページを壊します。宣言するコードが一度だけ実行されるようにするために私が行った長さは、率直に言ってばかげていますが、役に立ちません。tchild.phpの上部は現在次のようになっています。

(!( isset( $GLOBALS['tchild_counter'] ) ))
    ? $GLOBALS['tchild_counter'] = 1 
    : $GLOBALS['tchild_counter']++ ;
log_message("info", "tchild has been included " . $GLOBALS['tchild_counter'] . " times");

if($GLOBALS['tchild_counter'] != 1) {
    log_message("info", "STOP RUNNING TWICE");
} else {

if ( ! defined('BASEPATH')) {
    log_message("error", "BASEPATH not set; no direct script access allowed");
    exit('No direct script access allowed');
}
log_message("info", "Basepath is fine, checking if tchild exists (proc".getmypid().")");
log_message("info", "why does that last line seem to run twice?");
if ( ! class_exists('TChild')) {
log_message("info", "TChild does not exist, creating it");
if(class_exists('tchild')) {
    log_message("info", "tchild apparently exists?");
} else {
    log_message("info","okay, I'm extra-sure that tchild doesn't exist");
}

class TChild extends ActiveRecord\Model {

それは...何かの巨大な山ですが、少なくともTChildが一度だけ定義されることを保証する必要がありますよね?うーん、ダメ。ほとんどの場合、正常に動作しますが、サーバーが奇妙な状態になり、それとは反対のすべての証拠があるにもかかわらず、TChildが2回宣言されていると判断する場合があります。私が追加した広範なロギングステートメントから、tchild.phpは最初に単一のrequire_onceにのみ含まれ、クラス定義に2回以上到達することはないと確信しています。(ただし、正常に実行されている場合でも、2つの「STOPRUNNING TWICE」ログエントリが出力されます。理由はわかりませんが、少なくとも何も壊れません。)

失敗し始めると、(通常は)数分間すべてを壊し続け、その後、最初の失敗と同じくらい不思議な理由で自分自身を修正します。

ここで何が起こっているのかわかりません。グーグルで調べてみると、php.iniにapc.enabled = 0を追加しようとしましたが、クラッシュやパフォーマンスに違いはありませんでした。(そもそも有効になっているとは思いませんが、一見の価値があります。)

アップデート:

ああ、ファイルを複数回インクルードしているサードパーティのライブラリにrequireステートメントがありました。宣言をラップしたすべてのif/elseブロックにもかかわらず、クラスが再宣言された理由はまだわかりませんが、少なくとも現在は機能しているようです。

4

2 に答える 2

1

ファイルが複数回インクルードされているという事実を単にエコーするのではなく、PHP にそのファイルがどこから来たのかを教えてもらいます。

于 2012-08-22T23:02:37.640 に答える
0

log_message("info", "STOP RUNNING TWICE"); の後に戻るだけではどうでしょうか。戻る; または終了(0); ファイルが複数回含まれているようで、コードのどの部分でも停止することはありません。class TChild extends ActiveRecord\Modeland が再度宣言される部分に到達するだけです。

私があなたがするところなら:

if ( ! defined('BASEPATH')) {
    log_message("error", "BASEPATH not set; no direct script access allowed");
    exit('No direct script access allowed');
}

if (class_exists('TChild') || class_exists('tchild')) {
    log_message("info", "class already exists returning");
    return; // or exit(0);
}

class TChild extends ActiveRecord\Model {
…

追跡が困難な他のコードの山からファイルが含まれていない限り、ファイルがどこから含まれているかを確認する必要があるとあなたは私に尋ねました。しかし、上記のコードで十分です。xhprofまたはxdebugdebug_backtraceなど、他のユーティリティからファイルが含まれている場所を確認するために使用できます。

于 2012-08-22T22:48:10.607 に答える