Solusi untuk "Kesalahan fatal: Tingkat penyarangan fungsi maksimum '100' tercapai, dibatalkan!" di PHP

140

Saya telah membuat fungsi yang menemukan semua URL dalam file html dan mengulangi proses yang sama untuk setiap konten html yang ditautkan ke URL yang ditemukan. Fungsinya rekursif dan dapat berjalan tanpa henti. Namun, saya telah membatasi rekursi dengan menetapkan variabel global yang menyebabkan rekursi berhenti setelah 100 rekursi.

Namun, php mengembalikan kesalahan ini:

Kesalahan fatal: Tingkat penyarangan fungsi maksimum '100' tercapai, dibatalkan! di D: \ wamp \ www \ crawler1 \ simplehtmldom_1_5 \ simple_html_dom.php di baris 1355

KESALAHAN

Saya menemukan solusi di sini: Meningkatkan batas panggilan fungsi bersarang tetapi ini tidak berfungsi dalam kasus saya.

Saya mengutip salah satu jawaban dari tautan yang disebutkan di atas. Mohon pertimbangkan itu.

"Apakah Anda menginstal Zend, IonCube, atau xDebug? Jika demikian, mungkin dari situlah Anda mendapatkan kesalahan ini.

Saya mengalami ini beberapa tahun yang lalu, dan akhirnya Zend menempatkan batasan itu di sana, bukan PHP. Tentu saja menghapusnya akan membuat> Anda melewati 100 iterasi, tetapi pada akhirnya Anda akan mencapai batas memori. "

Apakah ada cara untuk meningkatkan level bersarang fungsi maksimum di PHP

Rafay
sumber
2
Selain itu: PHP tidak memiliki batasan pada panggilan fungsi bersarang, itu harus merupakan ekstensi yang Anda gunakan yang menyebabkan hal ini.
Abel
@Abel Saya yakin kode saya tidak memiliki kesalahan. Ada variabel statis yang menambah nilainya satu pada setiap panggilan rekursif. Jika variabel itu kurang dari 100, panggilan rekursif akan berlanjut hingga variabel mencapai 100. Maksud saya, variabel yang mencapai 100 sebenarnya adalah kasus dasar. Sedangkan error muncul sebelum 100 rekursi. Dan seperti yang Anda sebutkan bahwa beberapa ekstensi saya menyebabkan ini, saya ingin menyebutkan bahwa saya menggunakan fungsi dari simple_html_dom.php. Jika Anda memiliki ide tentang simple_html_dom.php, tolong bantu saya dalam hal ini. Silakan merujuk ke pertanyaan yang diperbarui.
Rafay
7
Itu adalah kesalahan oleh xdebug. Dari tangkapan layar terlihat Anda menggunakan xdebug. Anda dapat menonaktifkan setelan tersebut di sini: xdebug.max_nesting_level atau beri tahu seberapa besar tingkat bersarangnya.
hakre
3
jika menggunakan WAMP, perhatikan bahwa menonaktifkan xdebug di php.ini TIDAK selalu berhasil; hal yang sama berlaku untuk memperluas tingkat sarang yang diizinkan; bug menebak; SOLUSI: buka php.ini dan komentari php_xdebug - ???. Dll
Jeffz
Kemungkinan duplikat dari Meningkatkan batas panggilan fungsi bersarang
AL

Jawaban:

148

Tingkatkan nilai xdebug.max_nesting_leveldalam Andaphp.ini

Maxence
sumber
6
@AL Anda mengedit file php.ini dan menambahkan atau mengedit baris xdebug.max_nesting_level di bagian XDebug.
Maxence
3
Namun jika ini adalah lingkungan produksi, lihat jawaban yang diterima, yaitu menonaktifkan xdebug di lingkungan itu.
zkent
3
Ini menyelesaikan gejala (untuk sementara waktu), tetapi bukan masalahnya.
Sebastian Mach
1
Solusi ini berhasil untuk saya ketika saya menggunakan UFront for Haxe di MAMP.
Confidant
6
untuk tidak terbatas:xdebug.max_nesting_level = -1
Nabi KAZ
57

Solusi sederhana memecahkan masalah saya. Saya baru saja mengomentari baris ini:

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

di php.inifile saya . Ekstensi ini membatasi tumpukan 100jadi saya menonaktifkannya. Fungsi rekursif sekarang bekerja seperti yang diantisipasi.

Rafay
sumber
4
Jadi, akhirnya itu adalah ekstensi XDebug ... Tenang rasanya. Dalam dua hari Anda dapat menerima jawaban Anda sendiri sebagai jawaban yang diterima, jika Anda mau (dan melihat pertanyaan Anda sebelumnya, sebagian besar melewatkan jawaban yang diterima).
Abel
64
Berurusan dengan rekursi yang berlebihan tentu lebih baik daripada hanya mematikan pemantauan.
petesiss
7
Itu pendekatan yang berat. Jawaban di atas yang menyebutkan variabel untuk menyesuaikan kedalaman tumpukan maksimal adalah pendekatan yang lebih baik.
aredridel
7
Anda harus tidak mengaktifkan xdebug dalam lingkungan produksi.
HarryFink
2
omong kosong. Saya tidak bisa berhenti menertawakan solusi yang dipilih. Jadi PC saya tidak akan berhenti mengeluarkan suara, jadi saya menemukan solusinya. Matikan. :)
Kevin Remisoski
44

Daripada melakukan panggilan fungsi rekursif, gunakan model antrian untuk meratakan struktur.

$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;
}

Ada berbagai cara untuk menanganinya. Anda dapat melacak lebih banyak informasi jika Anda membutuhkan beberapa wawasan tentang asal atau jalur yang dilalui. Ada juga antrian terdistribusi yang dapat bekerja dengan model serupa.

Louis-Philippe Huberdeau
sumber
5
Dengan SPL Anda tidak perlu menemukan kembali antrian: php.net/manual/en/class.splqueue.php
Francesco
1
Antrean SPL mungkin memberikan sedikit lebih banyak kecepatan, tetapi saya suka menggunakan array untuk sebagian besar tugas sederhana. push / pop / shift / unshift semuanya disediakan.
Louis-Philippe Huberdeau
1
Ini jawaban yang benar. Hindari perubahan nilai default. Cobalah untuk mengoptimalkan kode Anda.
Junaid Atique
42

Solusi lain adalah menambahkan xdebug.max_nesting_level = 200php.ini Anda

bacar ndiaye
sumber
8
itu juga mungkin untuk melakukannya di php, misalnya di file konfigurasi proyek Anda. ini_set('xdebug.max_nesting_level', 200);
svassr
@ Htxryan Saya bukan ahli tetapi itu karena tumpukan panggilan Anda terlalu "dalam" (terlalu banyak fungsi yang memanggil fungsi lain). Skenario tipikal di mana ini terjadi adalah dengan fungsi rekursif. Pengaturan tersebut kemungkinan besar ada untuk menghindari rekursi "di luar kendali" karena bug dalam kode.
Bryan
@svassr Anda mungkin ingin mempertimbangkan untuk menambahkan tip itu sebagai jawaban terpisah atau menambahkan ke yang sudah ada, itu membantu saya tetapi hampir melewatkannya di komentar
Bryan
@Bryan baru saja menambahkan jawaban
svassr
23

Daripada menonaktifkan xdebug, Anda dapat mengatur batas yang lebih tinggi seperti

xdebug.max_nesting_level = 500

shahinam
sumber
@SebastianMach: dan, luar biasa, bertahun-tahun setelahnya, juga. :) (Seperti empat kali lagi, atau lebih. Orang tidak hanya tidak membaca sekarang, mereka bahkan tidak menggulir lagi.)
Sz.
1
@Sz .: Wow, ledakan yang luar biasa dari masa lalu: P Sangat mengejutkan.
Sebastian Mach
19

Anda juga dapat memperbaikinya secara langsung di php, misalnya di file konfigurasi proyek Anda.

ini_set('xdebug.max_nesting_level', 200);

svassr
sumber
1
Terima kasih, ini berfungsi dengan baik karena saya tidak perlu khawatir tentang memperbarui php.ini di semua kotak dev saya, saya hanya menambahkan ini ke file bootstrap aplikasi saya.
Bryan
13

Masuk ke file konfigurasi php.ini Anda dan ubah baris berikut:

xdebug.max_nesting_level=100

menjadi sesuatu seperti:

xdebug.max_nesting_level=200
Yasssine ELALAOUI
sumber
13

di Ubuntu menggunakan PHP 5.59:
harus `:

/etc/php5/cli/conf.d

dan temukan xdebug.ini Anda di direktori itu, dalam kasus saya adalah 20-xdebug.ini

dan tambahkan baris ini '

xdebug.max_nesting_level = 200


atau ini

xdebug.max_nesting_level = -1

atur ke -1 dan Anda tidak perlu khawatir mengubah nilai level bersarang.

`

Gujarat Santana
sumber
12

mungkin terjadi karena xdebug.

Coba beri komentar pada baris berikut di "php.ini" Anda dan mulai ulang server Anda untuk memuat ulang PHP.

  ";xdebug.max_nesting_level"

vandersondf.dll
sumber
2
atau menonaktifkan semua
xdebug
2
Bagaimana cara kerjanya? Jika Anda tidak menentukan batas secara manual, itu hanya akan kembali ke default, yaitu 100 ( xdebug.org/docs/basic ). Dengan mengomentari baris ini, semua yang Anda lakukan akan memaksa pengaturan untuk kembali ke default.
justanotherprogrammer
Menonaktifkan semua xdebug tidak disarankan jika Anda bergantung pada penggunaan alatnya; Biasanya konfigurasi "xdebug.max_nesting_level" digunakan tanpa mengetahui kegunaan aslinya, jadi umumnya komentar saja sudah cukup dan valid.
vandersondf
12

Coba cari di /etc/php5/conf.d/ untuk melihat apakah ada file bernama xdebug.ini

max_nesting_level adalah 100 secara default

Jika tidak diatur dalam file itu tambahkan:

xdebug.max_nesting_level=300

ke akhir daftar sehingga terlihat seperti ini

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

Anda kemudian dapat menggunakan pengujian @ Andrey sebelum dan sesudah melakukan perubahan ini untuk melihat apakah berhasil.

php -r 'function foo() { static $x = 1; echo "foo ", $x++, "\n"; foo(); } foo();'
Lee Woodman
sumber
Hebat, jawaban pertama yang menyebutkan bahwa xdebug memiliki .inifile terpisah . Omong-omong, ketika Anda menjalankan php5-fpm, file ini mungkin ada di suatu tempat di sini:/etc/php5/fpm/conf.d/20-xdebug.ini
Daan
7

php.ini:

xdebug.max_nesting_level = -1

Saya tidak sepenuhnya yakin apakah nilainya akan meluap dan mencapai -1, tetapi nilainya tidak akan pernah mencapai -1, atau akan menetapkan max_nesting_level cukup tinggi.

Martyn Shutt
sumber
1
Berhasil! Tidak masalah jika Anda menggunakan XDebug atau tidak, tidak juga jika Anda berkomentar di baris php.ini. Saya secara eksplisit menggunakan: ini_set ('xdebug.max_nesting_level', -1);
pengguna2928048
6

Anda dapat mengubah kode rekursif Anda menjadi kode iteratif, yang mensimulasikan rekursi. Ini berarti Anda harus mendorong status saat ini (url, dokumen, posisi dalam dokumen, dll.) Ke dalam array, ketika Anda mencapai tautan, dan mengeluarkannya dari larik, ketika tautan ini telah selesai.

Yogu
sumber
5

Anda dapat mencoba menggoyahkan penyarangan dengan menerapkan pekerja paralel (seperti dalam komputasi cluster) alih-alih meningkatkan jumlah panggilan fungsi bersarang.

Misalnya: Anda menentukan slot dalam jumlah terbatas (mis. 100) dan memantau jumlah "pekerja" yang ditugaskan untuk masing-masing / beberapa di antaranya. Jika ada slot yang menjadi kosong, Anda menempatkan pekerja yang menunggu "di dalamnya".

tamasgal.dll
sumber
1
Itu sebenarnya bukan pendekatan yang berlaku umum. Itu lebih masuk akal untuk diparalelkan, bukan menghindari kedalaman tumpukan.
aredridel
5

Periksa rekursi dari baris perintah:

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

jika hasil> 100 MAKA periksa batas memori;

Andrey
sumber
3

Jika Anda menggunakan Laravel, lakukan

composer update

Ini harusnya berhasil.

Putri Dewi Purnamasari
sumber
Anda harus menambahkan lebih banyak informasi latar belakang tentang ini. Ini bisa berguna meskipun laracasts.com/forum/…
ggderas
1
ini tidak ada hubungannya dengan pengaturan xdebug / php.ini yang bisa menjadi penyebab kesalahan. Mungkin juga aplikasi Anda dalam loop dos dan terus-menerus melakukan perulangan di sekitar suatu fungsi, tidak ada di mana OP menyatakan mereka menggunakan laravel dan melihat kodenya sip kemungkinannya adalah codeigniter
James Kirkby
3
<?php
ini_set('xdebug.max_nesting_level', 9999);
... your code ...

PS Ubah 9999 ke nomor yang Anda inginkan.

cofirazak.dll
sumber
1

Saya mengalami kesalahan ketika saya menginstal banyak plugin Jadi kesalahan 100 muncul termasuk lokasi plugin terakhir yang saya instal C: \ wamp \ www \ mysite \ wp-content \ plugins \ "..." jadi saya menghapus plugin ini folder di drive C: maka semuanya kembali normal.Saya pikir saya harus membatasi jumlah plug-in yang saya instal atau yang telah diaktifkan. semoga berhasil saya harap ini membantu

CalvinMD
sumber
1

Dalam kasus Anda, sudah pasti instance crawler memiliki lebih banyak batas Xdebug untuk melacak info kesalahan dan debug.

Tetapi, dalam kasus lain juga kesalahan seperti pada PHP atau file inti seperti pustaka CodeIgniter akan membuat kasus seperti itu dan jika Anda bahkan meningkatkan pengaturan level x-debug, itu tidak akan hilang.

Jadi, perhatikan kode Anda dengan cermat :).

Inilah masalah dalam kasus saya.

Saya memiliki kelas layanan yang merupakan perpustakaan di CodeIgniter. Memiliki fungsi didalamnya seperti ini.

 class PaymentService {

    private $CI;

    public function __construct() {

        $this->CI =& get_instance();

   }

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

Pengontrol saya sebagai berikut:

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

Pemanggilan fungsi pada baris terakhir salah karena salah ketik, mestinya seperti di bawah ini:

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

Kemudian saya terus mendapatkan pesan kesalahan melebihi. Tapi saya menonaktifkan XDebug tetapi tidak membantu. Dengan cara apa pun, silakan periksa nama kelas atau kode Anda untuk panggilan fungsi yang tepat.

Daniel Adenew
sumber
Apakah itu jawaban atau pertanyaan?
AL
@daniedad Saya mengedit jawaban Anda, saya pikir lebih baik menulis solusi dalam teks dan tidak hanya dalam komentar yang dilampirkan pada kode. Dan bentuk saat ini membuatku berpikir itu adalah pertanyaan baru dan bukan jawaban. Jangan ragu untuk melakukan rollback jika Anda tidak menyetujui perubahan tersebut.
AL
1

Saya mengalami masalah ini dengan WordPress di cloud9. Ternyata itu adalah plugin W3 Caching. Saya menonaktifkan plugin dan berfungsi dengan baik.

hanya kalau
sumber
1

Solusi lain jika Anda menjalankan skrip php di CLI (cmd)

File php.ini yang perlu diedit berbeda dalam kasus ini. Dalam instalasi WAMP saya, file php.ini yang dimuat di baris perintah adalah:

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

bukannya \ wamp \ bin \ apache \ apache2.4.9 \ bin \ php.ini yang dimuat ketika php dijalankan dari browser

Binod Kalathil
sumber
0

Anda juga dapat memodifikasi fungsi {debug} di modifier.debug_print_var.php, untuk membatasi rekursi menjadi objek.

Sekitar baris 45, sebelumnya:

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

Sesudah:

$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));

Dengan cara ini, Xdebug masih akan berperilaku normal: membatasi kedalaman rekursi di var_dump dan seterusnya. Karena ini adalah masalah yang cerdas, bukan masalah Xdebug!

theredled
sumber
0

Saya memiliki masalah yang sama dan saya kembali seperti ini:

Buka file MySQL my.ini

Di bagian [mysqld], tambahkan baris berikut: innodb_force_recovery = 1

Simpan file dan coba mulai MySQL

Hapus baris yang baru saja Anda tambahkan dan Simpan

Yassine Ech-Charafi
sumber