「致命的エラー:関数のネストの最大レベル「100」に達したため、中止します!」の解決策 PHPで


137

htmlファイル内のすべてのURLを検索し、検出されたURLにリンクされている各h​​tmlコンテンツに対して同じプロセスを繰り返す関数を作成しました。関数は再帰的で、無限に続行できます。ただし、100回の再帰後に再帰を停止させるグローバル変数を設定することで、再帰に制限を設けています。

ただし、phpは次のエラーを返します。

致命的なエラー:関数のネストレベルが最大 '100'に達したため、中止します!D:\ wamp \ www \ crawler1 \ simplehtmldom_1_5 \ simple_html_dom.phpの1355行目

エラー

私はここで解決策を見つけました:ネスト関数呼び出しの制限を増やしていますが、これは私の場合は機能しません。

上記のリンクからの回答の1つを引用しています。どうぞご検討ください。

「Zend、IonCube、またはxDebugがインストールされていますか?インストールされている場合、それはおそらくこのエラーの原因です。

私は数年前にこの問題に遭遇しましたが、PHPではなくZendがその制限をそこに置いていました。もちろん、それを削除すると、100回の繰り返しを超えてしまいますが、最終的にはメモリ制限に達します。 "

PHPで関数のネストの最大レベルを上げる方法はありますか


2
また、PHPにはネストされた関数呼び出しに制限はありません。これは、使用している拡張機能である必要があります。
Abel

@Abel私のコードにはエラーがないと確信しています。再帰呼び出しごとに値を1ずつ増やす静的変数があります。その変数が100未満の場合、変数が100に達するまで再帰呼び出しが続行されます。つまり、100に達する変数が実際には基本ケースであるということです。エラーは100回の再帰の前に発生します。そして、あなたが私の拡張機能がこれを引き起こしていると述べたように、私はsimple_html_dom.phpからの関数を使用していることを述べたいと思います。simple_html_dom.phpについて何か考えがあれば、この点で私を助けてください。更新された質問を参照してください。
ラファイ

7
これはxdebugによるエラーです。スクリーンショットから見えるようにxdebugを使用します。ここで設定を無効にすることができます:xdebug.max_nesting_levelまたはネストレベルの大きさを教えてください。
hakre

3
WAMPを使用する場合、php.iniでxdebugを無効にしても機能しない場合があることに注意してください。許可されたネストの拡張レベルにも同じことが当てはまります。バグは推測です。解決策:php.iniに移動してphp_xdebug-???。dllをコメント化します
Jeffz

回答:


145

値が増加xdebug.max_nesting_level中のあなたphp.ini


6
@AL php.iniファイルを編集し、XDebugセクションでxdebug.max_nesting_level行を追加または編集します。
Maxence

3
ただし、これが本番環境の場合は、その環境でxdebugを無効にするという、受け入れられた回答を参照してください。
zkent 2015

3
これで症状は(しばらくの間)解決しますが、問題は解決しません。
セバスチャンマッハ

1
このソリューションは、MAMPでHafrontにUFrontを使用していたときに機能しました。
機密保持者、2016年

4
無制限:xdebug.max_nesting_level = -1
Nabi KAZ 2018

55

簡単な解決策が私の問題を解決しました。私はこの行にコメントしました:

zend_extension = "d:/wamp/bin/php/php5.3.8/zend_ext/php_xdebug-2.1.2-5.3-vc9.dll

私のphp.iniファイルで。この拡張機能はスタックを制限していた100ため、無効にしました。再帰関数は期待どおりに機能しています。


4
結局のところ、結局それはXDebug拡張機能でした...知っておくと良いでしょう。2日以内に、必要に応じて、自分の回答を承認済みの回答として受け入れることができます(以前の質問を確認すると、ほとんどの場合、受け入れられた回答を見逃してしまいます)。
Abel

61
過度の再帰に対処することは、単に監視をオフにするよりも確かに優れています。
論点

7
それは強引なアプローチです。スタックの最大深度を調整するための変数について述べた上記の回答は、より優れたアプローチです。
aredridel

7
実稼働環境でxdebugが有効になっていないと思います。
HarryFink 2013

2
聖なるがらくた。選ばれた解決策に笑いが止まらない。だから私のPCは音を立てるのを止めませんでした、それで私は解決策を見つけました。消して。:)
ケビン・レミソスキ2017年

44

再帰的な関数呼び出しを行うのではなく、キューモデルを使用して構造をフラット化します。

$queue = array('http://example.com/first/url');
while (count($queue)) {
    $url = array_shift($queue);

    $queue = array_merge($queue, find_urls($url));
}

function find_urls($url)
{
    $urls = array();

    // Some logic filling the variable

    return $urls;
}

それを処理するにはさまざまな方法があります。起点または通過したパスに関する洞察が必要な場合は、さらに多くの情報を追跡できます。同様のモデルで機能する分散キューもあります。


5
SPLを使用すると、キューを作り直す
Francesco

1
SPLキューの方が速度は少し速いかもしれませんが、ほとんどの単純なタスクでは配列を使用するのが好きです。プッシュ/ポップ/シフト/シフト解除がすべて提供されます。
Louis-Philippe Huberdeau、2011

1
これが正解です。デフォルト値を変更しないでください。コードを最適化してください。
Junaid Atique

41

別の解決策はxdebug.max_nesting_level = 200、php.ini に追加することです


8
プロジェクトの構成ファイルなど、phpで行うこともできます。ini_set('xdebug.max_nesting_level', 200);
svassr

@htxryan私はエキスパートではありませんが、それは、コールスタックが「深すぎる」​​(他の関数を呼び出す関数が多すぎる)ためです。これが発生する一般的なシナリオは、再帰関数です。この設定は、コードのバグによる「制御不能」の再帰を回避するために存在する可能性があります。
ブライアン

@svassrあなたはそのヒントを別の答えとして追加するか、既存のヒントに追加することを検討したいかもしれません。それは私にとっては役に立ちましたが、コメントではほとんど見逃しました
Bryan

@Bryanが回答を追加しました
svassr 2015年

23

xdebugを無効にするのではなく、次のように上限を設定できます。

xdebug.max_nesting_level = 500


@SebastianMach:そして驚くべきことに、何年も経ちました。:)(あと4回ほど。人々は今読んでいないだけでなく、スクロールもしていません。)
Sz。

1
@Sz .:うわー、過去からの爆風:P驚くほど衝撃的です。
セバスチャンマッハ

18

これをphpで直接修正することもできます。たとえば、プロジェクトの構成ファイルで修正できます。

ini_set('xdebug.max_nesting_level', 200);


1
おかげで、すべての開発ボックスでphp.iniを更新する必要がないので、これはうまく機能します。これをアプリケーションのブートストラップファイルに追加するだけです。
ブライアン、

13

php.ini構成ファイルに移動して、次の行を変更します。

xdebug.max_nesting_level=100

次のようなものに:

xdebug.max_nesting_level=200

13

PHP 5.59を使用するUbuntuの場合:
`:

/etc/php5/cli/conf.d

そのディレクトリでxdebug.iniを見つけます。私の場合は 20-xdebug.iniです。

この行を追加します `

xdebug.max_nesting_level = 200


またはこれ

xdebug.max_nesting_level = -1

-1に設定すれば、ネストレベルの値を変更する必要はありません。

`


12

xdebugが原因で発生した可能性があります。

「php.ini」の次の行にコメントして、サーバーを再起動してPHPをリロードしてください。

  ";xdebug.max_nesting_level"


2
またはすべてのxdebugを無効化
zloctb

2
これはどのように機能しますか?手動で制限を定義しない場合は、デフォルトの100(xdebug.org/docs/basic)に戻ります。この行をコメント化することにより、設定を強制的にデフォルトに戻すことができます。
justanotherprogrammer

ツールの使用に依存している場合は、xdebugをすべて無効にすることはお勧めしません。通常、設定 "xdebug.max_nesting_level"は実際の使用法を知らずに使用されるため、通常はコメントのみで十分であり有効です。
vandersondf 2018

12

/etc/php5/conf.d/を調べて、xdebug.iniというファイルがあるかどうかを確認してください

max_nesting_levelはデフォルトで100です

そのファイルに設定されていない場合は、以下を追加します。

xdebug.max_nesting_level=300

リストの最後に移動すると、次のようになります。

xdebug.remote_enable=on
xdebug.remote_handler=dbgp
xdebug.remote_host=localhost
xdebug.remote_port=9000
xdebug.profiler_enable=0
xdebug.profiler_enable_trigger=1
xdebug.profiler_output_dir=/home/drupalpro/websites/logs/profiler
xdebug.max_nesting_level=300

その後、この変更を行う前後に@Andreyのテストを使用して、機能するかどうかを確認できます。

php -r 'function foo() { static $x = 1; echo "foo ", $x++, "\n"; foo(); } foo();'

xdebugには別の.iniファイルがあることを述べた最初の回答です。ところであなたはPHP5-FPMを実行すると、このファイルがどこかにここにおそらくある:/etc/php5/fpm/conf.d/20-xdebug.ini
大安

7

php.ini:

xdebug.max_nesting_level = -1

値がオーバーフローして-1に達するかどうかは完全にはわかりませんが、-1に達しないか、max_nesting_levelがかなり高く設定されます。


できます!XDebugを使用するかどうかに関係なく、php.iniの行をコメントアウトすることもありません。私は明示的に使用しました:ini_set( 'xdebug.max_nesting_level'、-1);
user2928048

6

再帰コードを反復コードに変換して、再帰をシミュレートできます。これは、リンクに到達したときに現在のステータス(URL、ドキュメント、ドキュメント内の位置など)を配列にプッシュし、このリンクが終了したときに配列からポップする必要があることを意味します。


5

ネスト関数呼び出しの数を増やす代わりに、(クラスターコンピューティングのように)並列ワーカーを実装することにより、ネストを小刻みに動かそうとすることができます。

例:限られた数のスロット(例:100)を定義し、それぞれに割り当てられた「ワーカー」の数を監視します。スロットが空くと、待機中のワーカーが「その中に」配置されます。


1
これは実際には一般的に適用可能なアプローチではありません。スタックの深さを避けずに、並列化する方が賢明です。
aredridel

5

コマンドラインから再帰を確認します。

php -r 'function foo() { static $x = 1; echo "foo ", $x++, "\n"; foo(); } foo();'

結果> 100の場合は、メモリ制限を確認します。


3

Laravelを使用している場合は、

composer update

これはうまくいくはずです。


これに関する背景情報をさらに追加する必要があります。が、これは有用である可能性laracasts.com/forum/...は
ggderas

1
これは、エラーの原因であるxdebug / php.ini設定には影響しません。アプリケーションがdosループにあり、関数の周りを継続的にループしている可能性があります。OPがどこにlaravelを使用していて、彼のコードを見ているかがcodeigniterである可能性がない
James Kirkby


1

多くのプラグインをインストールするときにエラーが発生したため、エラー100には、C:\ wamp \ www \ mysite \ wp-content \ plugins \ "..."をインストールした最後のプラグインの場所が含まれているため、このプラグインを削除しましたC:ドライブのフォルダーに移動すると、すべてが正常に戻りました。インストールするプラグインの数を制限するか、アクティブにしたと思います。


1

あなたの場合、それは間違いなくクローラーインスタンスがエラーをトレースし、情報をデバッグするためのより多くのXdebug制限を持っていることです。

しかし、他のケースでは、PHPのようなエラーやCodeIgniterライブラリのようなコアファイルがそのようなケースを作り出し、x-debugレベルの設定を増やしてもそれは消えません。

したがって、コードを注意深く調べてください:)。

これが私の場合の問題です。

CodeIgniterのライブラリであるサービスクラスがありました。このような機能を内蔵しています。

 class PaymentService {

    private $CI;

    public function __construct() {

        $this->CI =& get_instance();

   }

  public function process(){
   //lots of Ci referencing here...
   }

次のように私のコントローラー:

$this->load->library('PaymentService');
$this->process_(); // see I got this wrong instead  it shoud be like 

入力ミスのため、最後の行の関数呼び出しは間違っていましたが、代わりに以下のようになっているはずです:

$this->Payment_service->process(); //the library class name

その後、超過エラーメッセージが表示され続けました。しかし、私はXDebugを無効にしましたが、助けにはなりませんでした。とにかく、クラス名またはコードが適切な関数呼び出しかどうかを確認してください。


それは答えですか、それとも質問ですか?
AL

@daniedad私はあなたの答えを編集しました。コードに添付されたコメントだけでなく、テキストでソリューションを書く方が良いと思います。そして現在の形は、それが答えではなく新しい質問であると私に思わさせました。変更を承認しない場合は、遠慮なくロールバックしてください。
AL

1

cloud9上のWordPressでこの問題が発生しました。それはW3キャッシングプラグインでした。プラグインを無効にしたところ、問題なく動作しました。


1

CLI(cmd)でPHPスクリプトを実行している場合の別の解決策

この場合、編集が必要なphp.iniファイルは異なります。私のWAMPインストールでは、コマンドラインで読み込まれるphp.iniファイルは次のとおりです。

\wamp\bin\php\php5.5.12\php.ini

phpがブラウザーから実行されたときにロードされる\ wamp \ bin \ apache \ apache2.4.9 \ bin \ php.iniの代わりに


0

オブジェクトへの再帰を制限するためにmodifier.debug_print_var.phpの{debug}関数を変更することもできます。

45行目あたり、前:

$results .= '<br>' . str_repeat('&nbsp;', $depth * 2)
  . '<b> -&gt;' . strtr($curr_key, $_replace) . '</b> = '
  . smarty_modifier_debug_print_var($curr_val, ++$depth, $length);

後:

$max_depth = 10;
$results .= '<br>' . str_repeat('&nbsp;', $depth * 2)
  . '<b> -&gt;' . strtr($curr_key, $_replace) . '</b> = '
  . ($depth > $max_depth ? 'Max recursion depth:'.(++$depth) : smarty_modifier_debug_print_var($curr_val, ++$depth, $length));

この方法でも、Xdebugは通常どおりに動作します:var_dumpで再帰の深さを制限するなど。これは賢い問題なので、Xdebugの問題ではありません。


0

私は同じ問題を抱えていて、私はこのように愛しています:

MySQL my.iniファイルを開く

[mysqld]セクションで、次の行を追加します。innodb_force_recovery = 1

ファイルを保存してMySQLを起動してみてください

追加した行を削除して保存します

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.