2017-01-19 2 views
1

Пример из документации 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 инициализируется перед вызовом функции.

var $crypted = ''; 

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

ответ

1

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

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

  • НЕ объявляя переменную не вызовет «Уведомление» в любой версии - так что технически это не требуется.
  • заявление поэтому предпочтительная вещь. Как 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?

1

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

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

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

+0

В этом случае я знаю, что функция не будет использовать переменную для получения данных из нее. И я знаю, что он правильно возвращает значение переменной. Он также заключен в свой собственный метод. Поэтому я чувствую, что есть оправдание в том, чтобы просто оставить это ради уменьшения числа строк в этом случае. Мне было интересно, как другие относятся к этому, хотя.Спасибо за ваш ответ. –

+0

Да, у меня возникло соблазн проголосовать, чтобы закрыть его как основанный на мнениях =) –

+0

Я не знал о каких-либо технических последствиях, о которых я, возможно, не знал, если раньше забыл инициализацию переменных. Вот почему я решил создать вопрос. Спасибо за помощь! –

 Смежные вопросы

  • Нет связанных вопросов^_^