2016-04-20 64 views
2

或者更確切地說,「修復用作PHP數組鍵的未加引號的字符串」,但對於標題來說有點長。修復未引用的PHP數組鍵

我繼承了一個相當大的代碼庫,其中陣列是這樣寫的:

$array[id] = 0; 
$array[value] = "test" 

儘管此代碼實際工作,它拋出了很多Use of undefined constant通知,所以這些線路確實需要變成:

$array['id'] = 0; 
$array['value'] = "test" 

我們正在談論的數百個代碼千行傳播到幾千年的文件。

也有類似案例:

$_SESSION[user_information][access_bit][ACCESS_NULL] = 1; 

user_informationaccess_bit意味着是字符串和ACCESS_NULL是一個定義的常量。好的是,常量只能用大寫字母來定義。

而爲了讓事情變得更加有趣,我們也有JavaScript中的同一PHP文件,其中類似array[id] = 0;代碼是完全正常的。

我想有效地收拾這個爛攤子,敷在單引號所有這些不確定的常量,但我不知道一個簡單的查找/替換(甚至用正則表達式)將做到這一點。有什麼想法嗎?

+0

即使您使用基於標記器/分析器的工具來解決該問題,您也不會避免手動驗證。所以你也可以去做一個正則表達式修復,這個修復可以很容易地對上下文敏感。 – mario

回答

1

結果比我想象的要容易。

function fix_unquoted_array_keys($filename){ 
    if(!is_file($filename)){ 
     return "File not found!"; 
    } 
    $content = file_get_contents($filename); 
    $content = preg_replace('/^!|\$([a-zA-Z_]+)\[([a-z_]+)\]/','\$$1[\'$2\']',$content); 
    $content = preg_replace('/\]\[([a-z_]+)\]/','][\'$1\']',$content); 
    file_put_contents($filename,$content); 

    // Check the file just in case we break something. 
    @exec("php -l ".$filename." 2>&1",$syntax); 
    if($syntax[0] && strpos($syntax[0],"No syntax errors") === false){ 
     return $syntax[0]; 
    } 

    return "OK"; 
} 

第一preg_replace取代所有簡單陣列等$user[id]$user['id']。它留下了多維數組,如$user[data][id]$user['data'][id]。我故意不匹配大寫鍵,因爲它們是最可能定義的常量。

第二preg_replace作品上的所有後續鍵通過簡單地匹配前一個關鍵的關閉托架。

這可能不是最優雅的解決方案,但似乎它完成了這項工作。我現在正在檢查最近一小時的差異,我找不到一個失敗的地方。

P.S. PHP tokenizer在此任務上失敗,因爲它似乎還將未定義的常量轉換爲字符串,並將它們標記爲T_STRING

+0

您需要考慮var名稱中也可能有數字(如$ row2 [xxxx]),但仍然可以,這樣做的確很不錯。你可以使用'^!| \ $([a-zA-Z _] +)\ [([a-z _] +)\]'和'$$$ 1 [「$ 2 「]'。你今天先生救了我的網吧。 – LordNeo