修复不带引号的 PHP 数组键

Fix unquoted PHP array keys

或者说 "Fix unquoted strings used as PHP array keys" 但这对于标题来说有点长。

我继承了一个相当大的代码库,其中数组是这样写的:

$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 是定义的常量。好处是常量只用大写字母定义。

为了让事情更有趣,我们还在相同的 php 文件中添加了 javascript,其中像 array[id] = 0; 这样的代码非常好。

我想有效地清理这个烂摊子并将所有那些未定义的常量用单引号引起来,但我不确定一个简单的 find/replace(即使使用正则表达式)是否可以做到这一点。有什么想法吗?

事实证明比我想象的要容易。

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_]+)\]/','$[\'\']',$content);
    $content = preg_replace('/\]\[([a-z_]+)\]/','][\'\']',$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.