Значения по ссылке
Дано:
<?php
function getCount(&$a) { return count($a); }
$cnt = getCount( $foo );
var_dump($cnt);
$cnt = getCount( $foo['bar'] );
var_dump($cnt);
#EOF
Возникает вопрос, а что за $foo ? Отвечаю: не определен. Нет его. Что будет?
Логично же, что ошибка, да?
Нет, не совсем логично. Код отработает без ошибок и предупреждений, если у вас следующие версии интерпретатров:
- PHP 5.6.0–5.6.30
- PHP 7.0.0–7.1.13
- HHVM 3.18.5–3.22.0
При передаче объекта по ссылке, интерпретатор не проверяет его содержимое и структуру. Эта фича существовала до версии PHP 7.2 и уже с этой версии начали генерировать варнинги.
Warning: count(): Parameter must be an array or an object that implements Countable in /in/EV9Fh on line 3 int(0)
Warning: count(): Parameter must be an array or an object that implements Countable in /in/EV9Fh on line 3 int(0)
В принципе поведение логичное с точки зрения Си разработчика. Если параметр определен по ссылке, то он может быть инициализирован внутри функции, в которой он определен. Это сделано для возврата функцией сразу нескольких значений — эдакий Си стайл, где можно закинуть указателей, а потом в них напихать нужные значения.
С версии 7.2 начинают сыпаться предупреждения, но они нам говорят о том, что мы передаем значения неверного типа, а не о том, что мы оперируем несуществующими переменными.
Пруф на тест: https://3v4l.org/EV9Fh
Опять же эта задачка в копилку к задаче:
https://medium.com/@frontman/fun-php-1-19ad75ee78bb
При рефакторинге большого приложения очень сильно может подгадить такое поведение. Но тут надо понимать зачем и как писать такой код и когда стоит пользоваться ссылками, а когда нет.
UPD
Комментарий моего коллеги, с которым я когда-то работал в мамбе (https://www.facebook.com/mipxtx):
До версии 7.2 в функции count() не было проверок типов. Если бы ты обратился в своей функции к переданной переменной на чтение, то получил бы ворнинг так или иначе.
Про обращение все верно и при обращении ворнинги будут всегда — это логично. Фишка задачи именно в том, как обрабатываются параметры по ссылке.
Ты передаешь ссылку на элемент массива, указывая таким образом, что хочешь после выполнения получить массив с таким-то элементом. А вообще в пхп нет никакого смысла передавать параметры по ссылкам. Память ты не сэкономишь, они все copy-on-write. А возвращаемый результат функции должен быть одним. Несколько результатов нарушают принципы SOLID напрямую.