2009-10-06 14 views
14

Tengo una aplicación PHP "index.php" que, por diversas razones, necesita ejecutar otras secuencias de comandos PHP usando include_once en esa otra secuencia de comandos. Esa otra secuencia de comandos no es muy estable, ¿hay alguna manera de hacer una include_once segura que no detenga a la persona que llama?PHP robusto incluye para manejar los errores?

es decir:

<?php 

safely_include_once('badfile.php'); // MAY throw syntax error, parse error, other badness 
echo "I can continue execution after error"; 

?> 

(Yo sé lo que es una mala idea de que esto puede ser, etc., descanso asegurado que esto no es materia de producción respetuosa con el medio.)

Respuesta

6

Usted puede simplemente

@include "fileWithBadSyntax.php"; 

Que, de mis pruebas rápidas, funciona tanto para errores de análisis como para errores lanzados con trigger_error().

EDIT: Esto es completamente incorrecto. Vea la respuesta de sneak, que es correcta, aunque algo inútil.

+0

hace el trabajo, ¿sería posible capturar los detalles del error con este enfoque? –

+0

Este enfoque silenciará todos los errores. Vea la respuesta de KyleFarris para un método que detectará errores y, opcionalmente, puede mantenerlos en silencio (IE, manejo de errores personalizados). –

+0

De hecho, la respuesta de Kyle es más poderoso – timdev

2

¿Sería posible cambiar su arquitectura y convertir "badfile.php" en un servicio web? En lugar de incluirlo directamente en su base de código, lo llamaría a través de la red y analizaría o incluiría su resultado. Esto lo ayudará a evitar los errores de análisis, también podría evitar el código potencialmente malicioso si tiene el entorno de badfile.php limitado de forma adecuada (utilizando safe_mode o ejecutando un proceso de servidor web separado con privilegios limitados).

+1

@ pix0r: Esto ciertamente funcionaría, pero dependiendo del alcance de su proyecto, podría ser un poco exagerado y poco elegante. – KyleFarris

2

Usted podría hacer un bloque try/catch

<?php 
try { 
    include("someFile.php"); 
} catch (Exception $e) { 
    // Should probably write it to a log file, but... for brevity's sake: 
    echo 'Caught exception: ', $e->getMessage(), "\n"; 
} 
?> 

Ahora, sólo se incluirá el archivo si no hay error. Si hay un error, se saltará estas cosas y escribirá la excepción (como, en los comentarios, preferiblemente en un archivo de registro o algo así).

Para más información: http://us2.php.net/manual/en/language.exceptions.php

+10

Un error de análisis detendrá PHP en el medio del archivo incluido y no volverá al bloque 'catch'. – erjiang

+0

Hmm ... tienes razón. Shucks. – KyleFarris

-1

En badfile.php que podría hacer que devuelve un valor:

<?php 
//inestable instructions. 


return true; ?> 

a continuación en el archivo principal por la que podría hacer:

<?php 

if (require($badFile)) { 
    //if it was true continue with normal execution 
} else { 
    echo "Error: ". error_get_last(); 
} 
36

Ninguno de estas respuestas funcionarán El más votado, que dice @include(), terminará el primer script si hay un error de análisis en el archivo incluido.

No puede evaluar(), no puede intentar/atraparlo, y cada forma de llamada include o require terminará todo ejecución en el script.

Esta pregunta permanece ABIERTA y SIN RESOLVER.

http://bugs.php.net/bug.php?id=41810

trata de un error en PHP, esta funcionalidad ha estado ausente por lo menos desde 2006. Se clasifican el fallo como "falsa" porque, según ellos, incluye() y requiere() pasará a de compilación hora.

Esto sale por la ventana si está generando los argumentos de cadena para incluir() y/o require() en RUNTIME, o hacer un eval() sobre una cadena que contiene un código que ejecuta un include().

+0

Mejor respuesta en mi humilde opinión – Janning

+0

No tiene que haber una manera, WordPress es capaz de hacer esto. Si activa un complemento que tiene un error de sintaxis o genera un error de advertencia/fatal, se lo indica y continúa el script (deshabilitando el complemento y mostrando el mensaje de error). por ejemplo: "El complemento no se pudo activar porque desencadenó un error fatal". Creo que hace esto a través de un engaño de iframe, que no es ideal. Pero no estoy seguro. –

+0

La respuesta de Graben, usando la línea de comando del intérprete con el indicador '-f', funcionará. Es lento y parece un truco, pero hace el trabajo bien. –

-3

Aquí es la única solución real que he podido encontrar:

function safe_include($fn) { 
     $fc = file_get_contents($fn); 
     if(!eval($fc)) { 
       return 0; 
     } 
     return 1; 
} 

Tenga en cuenta que el código anterior significa que tiene que sacar las declaraciones de apertura de sus archivos a ser incluidos, o hacer lo siguiente:

eval("?>" . $fc) 

El problema es que no se puede llamar require() o incluir() o su _once() variantes en cualquier punto y esperar que no terminan todo, incluyendo cualquier controladores de errores. PHP detendrá completamente el procesamiento de todo cuando encuentre un error de análisis.

La única excepción a esto es la cadena dentro de un eval(). El problema es, sin embargo, que realmente no se puede hacer esto:

eval('require($fn);'); 

... porque la requieren() dentro de la cadena eval'd se sigue parada. Tienes que leer los contenidos, rezar para que el archivo en cuestión no incluya() o requiera() más y eval().

La verdadera solución? Omitir PHP. :/

2

solución agraciado por incluir-no-encontrado-archivo ....

 
function safe_require($incfile, $showfn=1) { 
    $a = explode(":", get_include_path()) ; 
    $a[] = ""; 
    $b = 0; 
    foreach($a as $p) { 
    if(!empty($p)) $p .= "/"; 
    $f = $p.$incfile; 
    if(file_exists($f)) { 
     $b = 1; 
     break; 
    } 
    } 
    if(!$b) 
    exit("Cannot proceed, required file " . 
      (($showfn) ? $incfile : "") . " is unavailable or server has timed out." 
     ); 
    require_once("$f"); 
} 
+0

Bastante bien, pero todavía no disponible. Imagine que el archivo se elimina después de verificar que existe ... – Pacerier

10

La única solución real, no pensaron que el más elegante, pero funciona es llamar a otro intérprete php que se analiza y ejecutar el script para nada más que verificar si produce un error de análisis o un mensaje de No se detectó ningún error para filtrar los mensajes de error como PHP Parse Error blablabla. al igual que el código hace:

<?php 
function ChkInc($file){ 
    return file_exists($file) && (substr(exec("php -l $file"), 0, 28) == "No syntax errors detected in"); 
} 
?> 

Esta idea surgió de gillis' comment a la página del manual include función en PHP doc.

+2

Esta es la única forma de hacerlo, actualmente. –

+1

Usando 'if' para devolver verdadero o falso?¿No suena esto como una locura? ¿Qué hay de malo en convertir su solución en una sola línea: 'return (substr (exec (" php -l $ file "), 0, 28) ==" No se detectaron errores de sintaxis en ");'? – trejder

+0

Derecha, actualizó la respuesta a la versión de un trazador de líneas. – Graben

Cuestiones relacionadas