Комментарий больше, чем ответ, но слишком длинный для окна комментариев. И увлекательный вопрос, который оставляет меня спрашивать «почему».
Чтобы ответить прямо:
- НЕ объявляя переменную не вызовет «Уведомление» в любой версии - так что технически это не требуется.
- заявление поэтому предпочтительная вещь. Как Alex Я предпочитаю декларировать для удобочитаемости и ясности. (Я также предпочитаю избегать таких функций, как
extract
, которые создают переменные из no-where.) Но я уверен, что другие не согласятся.
Но это приводит к вопросу о том, ПОЧЕМУ он работает так? И я с удовольствием узнаю.
Прежде всего следует отметить, что переменные и переменные передаются по ссылке изменился с PHP 5 на PHP 7. интересно читать здесь: https://nikic.github.io/2015/05/05/Internal-value-representation-in-PHP-7-part-1.html, что объясняет различия.
Но в обоих PHP переменные хранятся в пространстве zval с помощью счетчика ссылок, сколько раз указана переменная. (Этот документ выше - лучший пример, который я нашел на его объяснении, но есть еще в manual)
Когда вы расширяете PHP и добавляете новые функции, вы получаете переменные из Zend API, используя zend_parse_parameters
.Это означает, что переменные, переданные в функции, также хранятся в контейнере zval и передаются между API и расширением. (Further reading - это относится к PHP5, но похоже на PHP7).
Мое понимание (и я рад быть скорректировано) объясняется в образцах четыре кода:
1)
function increment($i) {
$i++;
}
increment(3);
Переменная 3
не объявлена (очевидно), но для этого нужно быть в контейнере zval для перехода к API. Это показывает , вызывающая функция имеет возможность генерировать переменную в контейнере zval. (Как это не реальная переменное, я предполагаю, что это «immmutable», но это предположение.)
2)
function increment($i) {
$i++;
}
increment($y);
Это ошибка, как $y
не объявлена первым. Notice: Undefined variable: y in test.php
. Таким образом, здесь он не может генерировать $y
и помещать его в локальную область.
3)
function increment($i) {
$i++;
}
$y = 0;
increment($y);
переменная объявлена и введена в Zval контейнер. При вызове функций refcount будет увеличен, чтобы он мог быть передан API. Работает так, как ожидалось.
4)
function increment(&$i) {
$i++;
}
increment(3);
Эта ошибка Fatal error: Only variables can be passed by reference in test.php
. Это говорит нам о том, что переменная 3
отклоняется zend_parse_parameters
, поскольку она знает, что она неизменяема или что вызывающая функция знает, что функция ожидает переменную по ссылке.
5)
function increment(&$i) {
$i++;
}
$y = 0;
increment($y);
Переменная $y
помещают в контейнер Zval в текущей области на первой линии, и генерирует опорный указатель на $y
(увеличение RefCount дважды).
6)
function increment(&$i) {
$i++;
}
increment($y);
Это где она идет груши формы ИМО: Несмотря на то, переменная не объявлена, но $y == 1
. Это означает, что функция должна как создать переменную, так и вставить в zval-контейнер в текущей области и сгенерировать указатель ссылки на $y
(увеличить коэффициент пересчета).
Для этого он должен знать, что функция ожидает значения по ссылке - иначе почему поведение отличается от 2?
И ничто из этого не отвечает, почему это другое. Просто потому, что может создать переменную (как показано в примере 1), почему это не в примере 2, но это в примере 6?
В этом случае я знаю, что функция не будет использовать переменную для получения данных из нее. И я знаю, что он правильно возвращает значение переменной. Он также заключен в свой собственный метод. Поэтому я чувствую, что есть оправдание в том, чтобы просто оставить это ради уменьшения числа строк в этом случае. Мне было интересно, как другие относятся к этому, хотя.Спасибо за ваш ответ. –
Да, у меня возникло соблазн проголосовать, чтобы закрыть его как основанный на мнениях =) –
Я не знал о каких-либо технических последствиях, о которых я, возможно, не знал, если раньше забыл инициализацию переменных. Вот почему я решил создать вопрос. Спасибо за помощь! –