2009-10-06 80 views
14

我有一個PHP應用程序「index.php」,由於各種原因,需要在其他腳本上使用include_once來運行其他PHP腳本。那另一個腳本不是很穩定,那麼有沒有辦法做一個安全include_once不會停止調用者?強大的PHP包含處理錯誤?

即:

<?php 

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

?> 

(我知道什麼是一個壞主意,這可能是等,放心,這不是生產環境的東西。)

回答

6

你可以

@include "fileWithBadSyntax.php"; 

從我的快速測試中,它對解析錯誤或trigger_error()引發的錯誤都有效。

編輯:這是完全錯誤的。看到潛行的答案,這是正確的,如果有點無益。

+0

工作是否可以通過這種方法捕獲錯誤細節? – 2009-10-06 19:13:54

+0

這種方法可以消除所有錯誤。請參閱KyleFarris的答案,該方法可以捕獲錯誤並可以選擇保持安靜(IE,自定義錯誤處理)。 – 2009-10-06 19:46:00

+0

事實上,凱爾的答案更強大 – timdev 2009-10-06 19:47:19

2

是否有可能更改您的架構並將「badfile.php」轉換爲Web服務?不要將其直接包含到代碼庫中,而要通過網絡調用它並解析或包含其輸出。這樣可以避免解析錯誤,如果badfile.php的環境受到適當限制(使用safe_mode或運行具有有限權限的單獨Web服務器進程),還可以避免潛在的惡意代碼。

+1

@ pix0r:這當然會起作用,但取決於他的項目範圍,它可能只是有點矯枉過正,不夠好看。 – KyleFarris 2009-10-08 15:13:28

2

你可以做一個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"; 
} 
?> 

現在,它只會包含的文件,如果沒有錯誤。如果出現錯誤,它會跳過這些東西並寫入異常(例如,在註釋中,最好寫入日誌文件或其他東西)。

欲瞭解更多信息: http://us2.php.net/manual/en/language.exceptions.php

+10

解析錯誤會在包含文件中間停止PHP,並且它不會返回到「catch」塊。 – erjiang 2009-10-07 17:46:15

+0

嗯......你說得對。哪里哪里。 – KyleFarris 2011-05-25 20:11:40

-1

在badfile.php你可以把它返回一個值:

<?php 
//inestable instructions. 


return true; ?> 

然後在主文件,你可以這樣做:的

<?php 

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

無這些答案將起作用。如果在包含的文件中存在解析錯誤,那麼對@include()說的頂級投票仍然會終止第一個腳本。

你不能eval()它,你不能嘗試/捕捉它,並且每個調用include或require的方法都將終止全部在腳本中的執行。

這個問題仍然是OPEN和UNSOLVED。

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

這是PHP的一個bug,並且至少自2006年他們歸類錯誤是「虛假的」,因爲,他們聲稱這一功能一直缺少的,包括()和需要()發生在編譯期時間。

如果在RUNTIME中生成包含()和/或require()的字符串參數,或者在包含運行include()的代碼的字符串上執行eval(),則會出現窗口。

+0

最佳答案恕我直言 – Janning 2011-05-25 07:52:18

+0

必須有一種方式,Wordpress能夠做到這一點。如果您激活了一個語法錯誤或生成警告/致命錯誤的插件,它會告訴您並繼續執行腳本(禁用插件並顯示錯誤消息)。例如:「插件無法激活,因爲它觸發了致命錯誤。」不過,我相信它通過iframe欺騙來做到這一點,但這並不理想。但我不確定。 – 2013-05-03 18:56:07

+0

Graben的答案,使用解釋器命令行和'-f'標誌,將會起作用。它很慢,看起來像一個黑客,但它確實完成了工作。 – 2013-07-02 14:15:21

-3

這裏是唯一真正的解決方案,我已經能夠找到:

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

注意的是,上面的代碼意味着你必須從你的要被包含的文件取出開幕式上發言,還是做以下:

eval("?>" . $fc) 

的問題是,你不能調用需要()或include()或它們的_once()在任何一點的變體,並期望他們不要終止一切,包括任何錯誤處理程序。當遇到分析錯誤時,PHP將完全停止處理所有事情。

唯一的例外是eval()中的字符串。問題是,雖然,你不能真正做到這一點:

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

......因爲需要()的eval'd字符串將仍然停止內。你必須閱讀內容,祈禱有問題的文件不包括()或需要()更多,並eval()它。

真正的解決方案?跳過PHP。 :/

2

優美的解決方法包括文件未找到....

 
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

非常好,但仍然failable。想象一下,在你驗證它存在之後,文件將被刪除.... – Pacerier 2013-07-13 01:50:36

10

唯一真正的解決方案,以爲不是最優雅之一,但工作原理是在另一個PHP解釋器來解析調用和執行該腳本,除了檢查它是否產生分析錯誤或未檢測到錯誤消息來過濾錯誤消息,如PHP Parse Error blablabla。這樣的代碼呢:

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

這個想法來自gillis' commentinclude功能手冊頁在PHP文檔。

+2

這是目前唯一的方法。 – 2013-07-02 14:13:51

+1

使用'if'返回true或false?這聽起來不是瘋狂嗎?將你的解決方案轉換成單行代碼有什麼問題:'return(substr(exec(「php -l $ file」),0,28)==「在檢測到沒有語法錯誤」);'? – trejder 2015-05-08 07:40:52

+0

對,更新了單行版本的答案。 – Graben 2015-05-08 17:58:51