Как я могу использовать регулярные выражения, чтобы поймать индексы массива без кавычек в коде PHP и заключить их в кавычки? - PullRequest
6 голосов
/ 03 мая 2019

PHP 7.2 обновил неопределенные постоянные ошибки с уведомления до предупреждения с рекомендацией, что в будущем они будут возвращать полную ошибку.

Я пытаюсь найти способ исправить их с помощью сценариев,в идеале через регулярное выражение, которое я могу запустить, чтобы проанализировать каждый файл PHP на сайте, найти все оскорбительные фрагменты кода и исправить их.

Я нашел несколько примеров того, как исправить один вариант, но ни одного длядругой, и это тот, с которым я ищу помощи.

Вот пример файла:

<?php

$array[foo] = "bar"; 
// this should become 
// $array['foo'] = "bar"

echo "hello, my name is $array[foo] and it's nice to meet you"; 
// would need to become 
// echo "hello, my name is " . $array['foo'] . " and it's nice to meet you";

?>

Я видел много вариантов, чтобы определить и изменить первый тип, но не для второго, где неопределенная константа находится внутри строки.В этом случае синтаксическому анализатору потребуется:

  1. Заменить $array[foo] на $array['foo']
  2. Найти всю переменную, завершить кавычки заранее, поставить a.с любой стороны, а затем снова открывать кавычки

Редактировать: в идеале одно регулярное выражение должно обрабатывать оба примера в примере кода за один проход - т.е. добавлять тики, а также добавлять кавычки / точки, если оно идентифицируетэто внутри строки.

Ответы [ 2 ]

1 голос
/ 05 мая 2019
$array[foo] = "bar"; 
// this should become 
// $array['foo'] = "bar"

Да, это всегда вызывало уведомление и всегда было плохой практикой.

echo "hello, my name is $array[foo] and it's nice to meet you"; 
// would need to become 
// echo "hello, my name is " . $array['foo'] . " and it's nice to meet you";

Нет, этот стиль никогда не вызывал уведомления и не делает этого сейчас. Фактически, используется в качестве примера в документации PHP. PHP никогда не уберет возможность интерполировать переменные массива в строках.


Ваш первый случай достаточно прост, чтобы разобраться с чем-то вроде этого:

$str = '$array[foo] = "bar";';
echo preg_replace("/(\\$[a-z_][a-z0-9_]*)\\[([a-z][a-z0-9_]*)\\]/", "$1['$2']", $str);

Но, конечно, нужно ловить только за пределами строки.

Как и в случае любой сложной грамматики, регулярные выражения никогда не будут такими надежными, как синтаксический анализатор грамматики. Поскольку вы анализируете PHP-код, наиболее точным решением будет использование собственного синтаксического анализатора PHP .

$php = <<< 'PHP'
<?php
$array[foo] = "bar"; // this line should be the only one altered.
$array['bar'] = "baz";
echo "I'm using \"$array[foo]\" and \"$array[bar]\" in a sentence";
echo 'Now I\'m not using "$array[foo]" and "$array[bar]" in a sentence';
PHP;

$tokens = token_get_all($php);
$in_dq_string = false;
$last_token = null;
$output = "";

foreach ($tokens as $token) {
    if ($last_token === "[" && is_array($token) && $token[0] === 319 && !$in_dq_string) {
        $output .= "'$token[1]'";
    } elseif (is_array($token)) {
        $output .= $token[1];
    } else {
        if ($token === "\"") {
            $in_dq_string = !$in_dq_string;
        }
        $output .= $token;
    }
    $last_token = $token;
}

echo $output;

Выход:

<?php
$array['foo'] = "bar"; // this line should be the only one altered.
$array['bar'] = "baz";
echo "I'm using \"$array[foo]\" and \"$array[bar]\" in a sentence";
echo 'Now I\'m not using "$array[foo]" and "$array[bar]" in a sentence';

Этот код должен учитывать некоторые крайние случаи, например, когда вы намеренно используете константу в качестве индекса массива.

0 голосов
/ 03 мая 2019

Это не идеально, но его можно безопасно запускать несколько раз ( пример )

$str = 'echo "hello, my name is $array[foo] and it\'s nice to meet you";';
echo preg_replace_callback('/\".*(\$.*\[[^\'].*[^\']\]).*\"/', function($match) {
    $search = ['[', ']'];
    $replace = ["['", "']"];
    $array = '" . ' . str_replace($search, $replace, $match[1]) . ' . "';

    return str_replace($match[1], $array, $match[0]);
}, $str);

Регулярное выражение ограничивается двойными кавычками (\"). Затем мы ищем $var[val], без галочек '. Как только мы захватили его, мы можем запустить его через обратный вызов, который выполняет двухэтапный str_replace. Первая оборачивает нашу совпавшую $var[val] двойными кавычками и вставляет галочки, а вторая вставляет ее во всю строку, используя найденное регулярное выражение, совпадающее

Это не сработает. Если у вас есть $array[foo] $array[bar], он получится как

" . $array['foo'] . "" . $array['bar'] . "

Не очень, но все еще действительный код

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...