Вы должны заранее установить переменную «передача по ссылке»?

Пример из документации PHP:

http://php.net/manual/en/function.openssl-public-encrypt.php

openssl_public_encrypt (
string $data , string &$crypted , mixed $key [, int $padding =
OPENSSL_PKCS1_PADDING ]
)

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

Во многих примерах я вижу, что $ crypted инициализируется перед вызовом функции.

var $crypted = '';

Это действительно необходимо (или технически более правильно), или это нормально, чтобы не устанавливать переменную, даже если это переменная «передача по ссылке»?

1

Решение

Скорее комментарий, чем ответ — но слишком долго для комментария. И увлекательный вопрос, который заставляет меня задаться вопросом «почему».

Чтобы ответить прямо:

  • НЕ объявив переменную, вы не увидите «ЗАМЕЧАНИЕ» ни в одной из версий, поэтому технически это не требуется.
  • поэтому декларирование является предпочтительной вещью. подобно Alex Я предпочитаю декларировать для удобочитаемости и ясности. (Я также предпочитаю избегать таких функций, как extract которые создают переменные из ниоткуда.) Но я уверен, что другие не согласятся.

Но это приводит к вопросу, ПОЧЕМУ это работает так? И я хотел бы знать.


Первое, на что следует обратить внимание, это то, что переменные и переменные, передаваемые по ссылке, сильно изменились с PHP 5 на PHP 7. Интересное прочтение здесь: https://nikic.github.io/2015/05/05/Internal-value-representation-in-PHP-7-part-1.html это объясняет различия.

Но в обоих PHP переменные хранятся в пространстве zval со счетчиком ссылок на то, сколько раз на переменную ссылаются. (Этот документ выше — лучший пример, который я нашел при объяснении, но есть больше в руководство)

Когда вы расширяете PHP и добавляете новые функции, вы получаете переменные из Zend API, используя zend_parse_parameters, Это означает, что переменные, передаваемые в функции, также хранятся в контейнере zval и передаются между API и расширением. (дальнейшее чтение — это относится к PHP5, но похоже на PHP7).

Мое понимание (и я рад, что меня поправили) объясняется в четырех примерах кода:

1)

function increment($i) {
$i++;
}

increment(3);

Переменная 3 не объявлено (очевидно), но оно должно быть в контейнере zval для передачи в API. Это показывает вызывающая функция может генерировать переменную в контейнере zval. (Поскольку это не настоящая переменная, я предполагаю, что она «неизменна», но это предположение.)

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 (увеличить счет в два раза).

6)

function increment(&$i) {
$i++;
}

increment($y);

Это то место, где оно имеет форму груши. ИМО: хотя переменная не объявлена, но $y == 1, Это означает, что функция должна как создать переменную, так и поместить ее в контейнер zval в текущей области видимости, а также сгенерировать указатель ссылки на $y (увеличить счет).

Для этого он должен знать, что функция ожидает значение по ссылке — в противном случае, почему поведение отличается от 2?

И ни один из этих ответов не объясняет, почему все по-другому. Просто потому что Можно создать переменную (как показано в примере 1), почему не в примере 2, а в примере 6?

1

Другие решения

Хотя переменная будет создана, я предпочитаю устанавливать ее явно по ряду причин:

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

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

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector