2009-10-06 24 views
14

Ho un'app PHP "index.php" che, per vari motivi, ha bisogno di eseguire altri script PHP usando include_once su quell'altro script. Questo altro script non è molto stabile, quindi c'è un modo per fare una cassaforte include_once che non fermerà il chiamante?Include robusti PHP per gestire gli errori?

cioè:

<?php 

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

?> 

(So quello che un'idea cattiva questo può essere, ecc, resto assicurato questo non è roba di produzione-ambiente.)

risposta

6

Si può solo

@include "fileWithBadSyntax.php"; 

Che, dai miei test rapidi, funziona sia per errori di analisi sia per errori lanciati con trigger_error().

EDIT: Questo è completamente sbagliato. Vedi la risposta di nascosto, che è corretta, anche se un po 'inutile.

+0

Il lavoro, sarebbe possibile acquisire i dettagli dell'errore con questo approccio? –

+0

Questo approccio farà tacitare tutti gli errori. Vedi la risposta di KyleFarris per un metodo che cattura gli errori e può opzionalmente tenerli tranquilli (IE, gestione degli errori personalizzati). –

+0

In effetti, la risposta di Kyle è più potente. – timdev

2

Sarebbe possibile modificare la propria architettura e trasformare "badfile.php" in un servizio Web? Invece di includerlo direttamente nella base di codice, lo chiameresti sulla rete e analizzeresti o includerai l'output. Questo ti porterà in giro errori di analisi, potresti anche evitare codice potenzialmente dannoso se l'ambiente di badfile.php è limitato in modo appropriato (usando safe_mode, o eseguendo un processo di server web separato con privilegi limitati).

+1

@ pix0r: Certamente funzionerebbe, ma a seconda della portata del suo progetto potrebbe essere un po 'eccessivo e poco elegante. – KyleFarris

2

Si potrebbe fare un blocco 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"; 
} 
?> 

Ora, sarà solo includere il file se non ci sono errori. Se c'è un errore, salterà questa roba e scriverà l'eccezione (come, nei commenti, preferibilmente in un file di registro o qualcosa del genere).

Per maggiori informazioni: http://us2.php.net/manual/en/language.exceptions.php

+10

Un errore di analisi interromperà PHP nel mezzo del file incluso e non tornerà al blocco 'catch'. – erjiang

+0

Hmm ... hai ragione. Shucks. – KyleFarris

-1

In badfile.php si potrebbe fare restituisce un valore:

<?php 
//inestable instructions. 


return true; ?> 

poi sul file principale si poteva fare:

<?php 

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

Nessuno di queste risposte funzioneranno. Il top-votato, che dice a @include(), terminerà ancora il primo script se c'è un errore di analisi nel file incluso.

Non è possibile eval() esso, non è possibile provare/prenderlo, e ogni modo di chiamare include o richiedere terminerà tutte le esecuzione nello script.

Questa domanda rimane APERTA e NON RISOLTA.

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

Si tratta di un bug in PHP, e questa funzionalità è mancato almeno dal 2006. classificati il ​​bug come "falsa", perché, sostengono, include() e richiede() accadere in di compilazione tempo.

Questo esce dalla finestra se si generano gli argomenti stringa da includere() e/o require() in RUNTIME, o facendo un eval() su una stringa contenente codice che esegue un include().

+0

Risposta migliore IMHO – Janning

+0

Ci deve essere un modo, Wordpress è in grado di farlo. Se attivi un plug-in che ha un errore di sintassi o genera un avviso/errore fatale, ti dice questo e continua lo script (disabilitando il plugin e mostrando il messaggio di errore). es .: "Impossibile attivare il plugin perché ha provocato un errore fatale." Credo che lo faccia attraverso l'inganno iframe, che non è l'ideale. Ma non sono sicuro. –

+0

La risposta di Graben, usando la riga di comando dell'interprete con il flag '-f', funzionerà. È lento e sembra un hack, ma ha fatto il lavoro. –

-3

Ecco l'unica vera soluzione sono stato in grado di trovare:

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

Si noti che il codice di cui sopra significa che dovete togliere le dichiarazioni di apertura dai file to-be-inclusi, o fare il seguente:

eval("?>" . $fc) 

Il problema è che non si possono chiamare require() o includere() o la loro _once() varianti in qualsiasi punto e si aspettano loro di non terminare tutto, compresi eventuali gestori di errori. PHP interromperà completamente l'elaborazione di tutto quando incontra un errore di analisi.

L'unica eccezione a questa è la stringa all'interno di un eval(). Il problema è, però, che non si può davvero fare questo:

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

... perché la richiede() all'interno della stringa di eval'd sarà ancora arresto. Devi leggere nei contenuti, pregare che il file in questione non includa() o require() ulteriormente, ed eval() it.

La vera soluzione? Salta PHP. :/

2

soluzione Graceful per includere-file-not-found ....

 
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

Abbastanza buono, ma ancora disponibile. Immagina che il file venga eliminato dopo aver verificato che esista ... – Pacerier

10

L'unica vera soluzione, non è pensato che il più elegante, ma funziona è quello di chiamare in un altro interprete PHP che analizza e eseguire lo script per nient'altro che controllare se produce un errore di analisi o un messaggio Nessun errore rilevato per filtrare i messaggi di errore come errore Parse PHP blablabla. come fa questo codice:

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

questa idea è nata da gillis' comment alla pagina di manuale include funzione in PHP doc.

+2

Questo è l'unico modo per farlo al momento. –

+1

Utilizzare 'if' per restituire true o false?Non sembra una follia? Cosa c'è di sbagliato nel convertire la tua soluzione in one-liner: 'return (substr (exec (" php -l $ file "), 0, 28) ==" Nessun errore di sintassi rilevato in ");'? – trejder

+0

Destra, ha aggiornato la risposta alla versione a una fodera. – Graben

Problemi correlati