Solución para "Error fatal: ¡Se alcanzó el nivel máximo de anidación de la función de '100', abortando!" en PHP

137

He creado una función que encuentra todas las URL dentro de un archivo html y repite el mismo proceso para cada contenido html vinculado a las URL descubiertas. La función es recursiva y puede continuar sin cesar. Sin embargo, he puesto un límite a la recursión estableciendo una variable global que hace que la recursión se detenga después de 100 recursiones.

Sin embargo, php devuelve este error:

Error fatal: nivel máximo de anidación de la función de '100' alcanzado, ¡abortando! en D: \ wamp \ www \ crawler1 \ simplehtmldom_1_5 \ simple_html_dom.php en la línea 1355

ERROR

Encontré una solución aquí: aumentar el límite de llamadas a la función de anidación, pero esto no funciona en mi caso.

Cito una de las respuestas del enlace mencionado anteriormente. Por favor, considérelo.

"¿Tiene instalado Zend, IonCube o xDebug? Si es así, es probable que ese sea el origen de este error.

Me encontré con esto hace unos años, y terminó siendo Zend poniendo ese límite allí, no PHP. Por supuesto, eliminarlo te permitirá superar las 100 iteraciones, pero eventualmente alcanzarás los límites de memoria ".

¿Hay alguna manera de aumentar el nivel máximo de anidación de funciones en PHP

Rafay
fuente
2
Además: PHP no tiene un límite en las llamadas a funciones anidadas, debe ser una extensión que esté usando lo que causa esto.
Abel
@Abel Estoy seguro de que mi código no tiene errores. Hay una variable estática que incrementa su valor en uno en cada llamada recursiva. Si esa variable es inferior a 100, las llamadas recursivas continúan hasta que la variable alcanza 100. Quiero decir que la variable que alcanza 100 es en realidad el caso base. Mientras que el error surge antes de 100 recursiones. Y como ha mencionado que alguna extensión puede estar causando esto, me gustaría mencionar que estoy usando funciones de simple_html_dom.php. Si tienes alguna idea sobre simple_html_dom.php, por favor, ayúdame a este respecto. Por favor, consulte la pregunta actualizada.
Rafay
77
Ese es un error de xdebug. De la captura de pantalla está visible, usa xdebug. Puede deshabilitar la configuración aquí: xdebug.max_nesting_level o indicar qué tan grande es el nivel de anidación.
Hakre
3
si usa WAMP, tenga en cuenta que deshabilitar xdebug en php.ini NO siempre funciona; lo mismo se aplica al nivel extendido de anidación permitida; un error una suposición; SOLUCIÓN: vaya a php.ini y comente php_xdebug - ???.
Dll

Respuestas:

145

Aumentar el valor de xdebug.max_nesting_levelen suphp.ini

Maxence
fuente
66
@AL Edita su archivo php.ini y agrega o edita la línea xdebug.max_nesting_level en la sección XDebug.
Maxence
3
Sin embargo, si este es un entorno de producción, consulte la respuesta aceptada, que es deshabilitar xdebug en ese entorno.
zkent
3
Esto resuelve el síntoma (por un tiempo), pero no el problema.
Sebastian Mach
1
Esta solución funcionó para mí cuando estaba usando UFront para Haxe en MAMP.
Confiado
44
por tiempo ilimitado:xdebug.max_nesting_level = -1
Nabi KAZ
55

Una solución simple resolvió mi problema. Acabo de comentar esta línea:

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

en mi php.iniarchivo Esta extensión estaba limitando la pila, 100así que la desactivé. La función recursiva ahora funciona según lo previsto.

Rafay
fuente
44
Entonces, eventualmente fue la extensión XDebug después de todo ... Es bueno saberlo. En dos días puede aceptar su propia respuesta como respuesta aceptada, si lo desea (y echar un vistazo a sus preguntas anteriores, la mayoría pierde una respuesta aceptada).
Abel
61
Lidiar con la recursividad excesiva seguramente es mejor que simplemente apagar el monitoreo.
Petesiss
77
Ese es un enfoque de mano dura. Las respuestas anteriores que mencionan la variable para ajustar la profundidad máxima de la pila es un mejor enfoque.
aredridel
77
No debe tener xdebug habilitado en un entorno de producción.
HarryFink
2
Santo cielo. No puedo dejar de reírme de la solución elegida. Para que mi PC no dejara de hacer ruido, encontré la solución. Apágalo. :)
Kevin Remisoski
44

En lugar de buscar llamadas a funciones recursivas, trabaje con un modelo de cola para aplanar la estructura.

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

Hay diferentes formas de manejarlo. Puede realizar un seguimiento de más información si necesita información sobre el origen o los caminos recorridos. También hay colas distribuidas que pueden funcionar con un modelo similar.

Louis-Philippe Huberdeau
fuente
55
Con SPL no necesita reinventar la cola: php.net/manual/en/class.splqueue.php
Francesco
1
SPL Queue puede proporcionar un poco más de velocidad, pero me gusta apegarme a los arreglos para la mayoría de las tareas simples. Se proporcionan push / pop / shift / unshift.
Louis-Philippe Huberdeau
1
Esta es la respuesta correcta. Evite el cambio de los valores predeterminados. Intenta optimizar tu código.
Junaid Atique
41

Otra solución es agregar xdebug.max_nesting_level = 200en su php.ini

bacar ndiaye
fuente
8
También es posible hacerlo en PHP, por ejemplo en el archivo de configuración de su proyecto. ini_set('xdebug.max_nesting_level', 200);
svassr
@htxryan No soy un experto, pero se debe a que la pila de llamadas es demasiado "profunda" (demasiadas funciones que llaman a otras funciones). El escenario típico donde esto ocurre es con una función recursiva. Es muy probable que la configuración esté allí para evitar la recursión "fuera de control" debido a un error en el código.
Bryan
@svassr, es posible que desee considerar agregar ese consejo como una respuesta separada o agregar a uno existente, fue útil para mí, pero casi lo perdí en los comentarios
Bryan
@Bryan acaba de agregar una respuesta
svassr
23

En lugar de deshabilitar el xdebug, puede establecer el límite superior como

xdebug.max_nesting_level = 500

shahinam
fuente
@SebastianMach: y, sorprendentemente, años después también. :) (Como cuatro veces más, más o menos. La gente no solo no lee ahora, sino que ya ni siquiera se desplaza.)
Sz.
1
@Sz .: Wow, qué maravilla del pasado: P Increíblemente impactante.
Sebastian Mach
18

También es posible arreglar esto directamente en php, por ejemplo en el archivo de configuración de su proyecto.

ini_set('xdebug.max_nesting_level', 200);

svassr
fuente
1
Gracias, esto funciona bien ya que no tengo que preocuparme por actualizar php.ini en todos mis cuadros de desarrollo, solo agrego esto al archivo de arranque de mi aplicación.
Bryan
13

Vaya a su archivo de configuración php.ini y cambie la siguiente línea:

xdebug.max_nesting_level=100

a algo como:

xdebug.max_nesting_level=200
Yasssine ELALAOUI
fuente
13

en Ubuntu usando PHP 5.59:
llegó a `:

/etc/php5/cli/conf.d

y encuentre su xdebug.ini en ese directorio, en mi caso es 20-xdebug.ini

y agrega esta línea `

xdebug.max_nesting_level = 200


o esto

xdebug.max_nesting_level = -1

configúrelo en -1 y no tendrá que preocuparse de cambiar el valor del nivel de anidación.

``

Gujarat Santana
fuente
12

Probablemente sucedió debido a xdebug.

Intente comentar la siguiente línea en su "php.ini" y reinicie su servidor para volver a cargar PHP.

  ";xdebug.max_nesting_level"

vandersondf
fuente
2
o deshabilitado todo xdebug
zloctb
2
¿Cómo funcionaría esto? Si no define el límite manualmente, simplemente volverá al valor predeterminado, que es 100 ( xdebug.org/docs/basic ). Al comentar esta línea, todo lo que hace obliga a la configuración a volver al valor predeterminado.
justanotherprogrammer
Deshabilitar todo xdebug no se recomienda si depende de su uso de la herramienta; Normalmente, la configuración "xdebug.max_nesting_level" se usa sin conocer su uso real, por lo que generalmente solo un comentario es suficiente y válido.
vandersondf
12

Intente buscar en /etc/php5/conf.d/ para ver si hay un archivo llamado xdebug.ini

max_nesting_level es 100 por defecto

Si no está configurado en ese archivo, agregue:

xdebug.max_nesting_level=300

al final de la lista para que se vea así

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

entonces puede usar la prueba de @ Andrey antes y después de hacer este cambio para ver si funciona

php -r 'function foo() { static $x = 1; echo "foo ", $x++, "\n"; foo(); } foo();'
Lee Woodman
fuente
Genial, la primera respuesta que menciona que xdebug tiene un .iniarchivo separado . Por cierto, cuando ejecutas php5-fpm este archivo probablemente esté en algún lugar aquí:/etc/php5/fpm/conf.d/20-xdebug.ini
Daan
7

php.ini:

xdebug.max_nesting_level = -1

No estoy completamente seguro de si el valor se desbordará y alcanzará -1, pero nunca alcanzará -1 o establecerá el max_nesting_level bastante alto.

Martyn Shutt
fuente
¡Funciona! No importa si usa XDebug o no, tampoco si comenta la línea en php.ini. Usé explícitamente: ini_set ('xdebug.max_nesting_level', -1);
user2928048
6

Puede convertir su código recursivo en un código iterativo, que simula la recursividad. Esto significa que debe insertar el estado actual (url, documento, posición en el documento, etc.) en una matriz, cuando llegue a un enlace, y sacarlo de la matriz, cuando este enlace haya finalizado.

Yogu
fuente
5

Puede intentar reducir la anidación implementando trabajadores paralelos (como en la computación en clúster) en lugar de aumentar el número de llamadas a funciones de anidación.

Por ejemplo: usted define un número limitado de espacios (por ejemplo, 100) y monitorea el número de "trabajadores" asignados a cada uno de ellos. Si alguna de las máquinas tragamonedas queda libre, usted pone a los trabajadores en espera "en ellas".

tamasgal
fuente
1
Ese no es realmente un enfoque generalmente aplicable. Es más sensato paralelizar, no evitar la profundidad de la pila.
aredridel
5

Verifique la recursividad desde la línea de comando:

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

si el resultado> 100 ENTONCES verifique el límite de memoria;

Andrey
fuente
3

Si estás usando Laravel, haz

composer update

Esto debería ser trabajo.

Putri Dewi Purnamasari
fuente
Debería agregar más información de fondo sobre esto. Esto podría ser útil aunque laracasts.com/forum/…
ggderas
1
Esto no tiene relación con la configuración de xdebug / php.ini, que podría ser la causa del error. También es posible que su aplicación esté en un bucle de dos y continuamente en bucle alrededor de una función, en ningún lugar OP declaró que estaban usando laravel y mirando su sorbo de código es probable que sea codeigniter
James Kirkby
3
<?php
ini_set('xdebug.max_nesting_level', 9999);
... your code ...

PD Cambie 9999 a cualquier número que desee.

cofirazak
fuente
1

Tuve un error cuando estaba instalando muchos complementos. Así que el error 100 mostró, incluyendo la ubicación del último complemento que instalé C: \ wamp \ www \ mysite \ wp-content \ plugins \ "...", así que eliminé este complemento carpeta en el disco C: luego todo volvió a la normalidad. Creo que tengo que limitar la cantidad de complementos que instalo o he activado. Buena suerte, espero que ayude

CalvinMD
fuente
1

En su caso, definitivamente es la instancia del rastreador que tiene más límite de Xdebug para rastrear información de error y depuración.

Pero, en otros casos, también los errores como en PHP o los archivos centrales como las bibliotecas CodeIgniter crearán un caso así y si incluso aumenta la configuración del nivel de depuración x, no desaparecerá.

Entonces, mire su código cuidadosamente :).

Aquí estaba el problema en mi caso.

Tuve una clase de servicio que es la biblioteca en CodeIgniter. Tener una función dentro como esta.

 class PaymentService {

    private $CI;

    public function __construct() {

        $this->CI =& get_instance();

   }

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

Mi controlador de la siguiente manera:

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

La llamada a la función en la última línea fue incorrecta debido al error tipográfico, en cambio debería haber sido como a continuación:

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

Luego seguía recibiendo el mensaje de error exceder. Pero deshabilité XDebug pero no ayudó. De cualquier manera, verifique el nombre de su clase o su código para ver la función adecuada.

Daniel Adenew
fuente
¿Es una respuesta o una pregunta?
AL
@daniedad Edité su respuesta, creo que es mejor escribir la solución en texto y no solo en los comentarios adjuntos al código. Y la forma actual me hizo pensar que era una pregunta nueva y no una respuesta. Siéntase libre de retroceder si desaprueba los cambios.
AL
1

Tuve este problema con WordPress en cloud9. Resulta que era el plugin W3 Caching. Deshabilité el complemento y funcionó bien.

que así sea
fuente
1

Otra solución si está ejecutando script PHP en CLI (cmd)

El archivo php.ini que necesita editar es diferente en este caso. En mi instalación de WAMP, el archivo php.ini que se carga en la línea de comando es:

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

en lugar de \ wamp \ bin \ apache \ apache2.4.9 \ bin \ php.ini que se carga cuando php se ejecuta desde el navegador

Binod Kalathil
fuente
0

También puede modificar la función {debug} en modifier.debug_print_var.php, para limitar su recursión en objetos.

Alrededor de la línea 45, antes:

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

Después :

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

De esta manera, Xdebug seguirá comportándose normalmente: limite la profundidad de recursión en var_dump y así sucesivamente. Como este es un problema inteligente, ¡no Xdebug!

theredled
fuente
0

Tuve el mismo problema y reslove así:

Abra el archivo MySQL my.ini

En la sección [mysqld], agregue la siguiente línea: innodb_force_recovery = 1

Guarde el archivo e intente iniciar MySQL

Elimine la línea que acaba de agregar y guarde

Yassine Ech-Charafi
fuente