Сегодня еще один пост о всяких веселых способах написать код в php.
Всем известно (а если не известно, то читайте мануал), что в строках в двойных кавычках переменные и некоторые другие выражения обрабатываются и вместо этой переменной\выражения выводится результат. Простейший пример:
$number = 42;
echo "Number is $number";
// outputs "Number is 42"
Теперь зададимся вопросом - а можно ли как-то интерпретировать в строках какие-либо выражения? Например, сложение двух чисел. Естественно, написание в лоб приводит к ошибкам:
$a = 42;
$b = 24;
echo "Sum is {$a + $b}";
Что же делать? Понятно, что можно завести класс, объявить в нем метод суммирования, но это как-то много кода:
class Summator {
public function sum($a, $b) {
return $a + $b;
}
}
$a = 42;
$b = 24;
$o = new Summator();
echo "Sum is {$o->sum($a, $b)}";
// outputs "Sum is 66"
Подумав еще немного можно прийти к следующему - создадим переменную, которая будет хранить анонимную функцию, и в строке вызовем эту переменную:
$a = 42;
$b = 24;
$sum = function($a, $b) { return $a + $b; };
echo "Sum is {$sum($a, $b)}";
// outputs "Sum is 66"
А с учетом стрелочных функций (с версии 7.4), которые имеют доступ к переменным родительской области видимости, код упрощается до такого:
$a = 42;
$b = 24;
$sum = fn() => $a + $b;
echo "Sum is {$sum()}";
// outputs "Sum is 66"
Ну и наконец самая безумная версия:
$a = 42;
$b = 24;
echo "Sum is ${0 * ${0}=$a+$b}";
// outputs "Sum is 66"
Что же здесь происходит?
Здесь мы пытаемся вывести переменную с названием, которое получается как результат умножения 0
на переменную ${0}
. А значение ${0}
является суммой значений $a
и $b
. Почему php выполняет присваивание значения переменной при парсинге строки - не знаю. Но тем не менее, мы получаем, что переменной ${0}
присваивается 66
. А так как результатом присваивания является присвоенное значение, то 0 * ${0}=$a+$b
превращается в 0 * 66
, и выражение ${0 * ${0}=$a+$b}
сворачивается в ${0}
. То есть мы хотим вывести переменную с названием 0
, которую мы уже определили ранее, как сумму $a
и $b
. Вот и получаем в выводе 66
.
Спасибо за внимание и никогда не пишите такой код)