#php #reference #conditional-operator
Вопрос:
Простой вопрос, простой код. Это работает:
$x = amp;$_SESSION['foo'];
Это не означает:
$x = (isset($_SESSION['foo']))?amp;$_SESSION['foo']:false;
Это бросает PHP Parse error: syntax error, unexpected 'amp;'
. Просто ли невозможно передать ссылку при использовании условного оператора, и почему бы и нет? Также это происходит, если между ?
и есть пробел amp;
.
Комментарии:
1. Какая версия PHP? AFAIU, с PHP 5.3 вы можете использовать: $x = amp;($_SESSION[‘foo’]) ?: false;
2. Извините, я случайно вырезал его; 5.2.8, к сожалению.
3. @Milan, который вызовет E_NOTICE, если элемент $_SESSION[‘foo’] не существует
Ответ №1:
В самом простом случае это выражение, которое является незаконным;
$c = condition ? amp;$a : amp;$b; // Syntax error
можно написать так:
$c = amp;${ condition ? 'a' : 'b' };
В вашем конкретном случае, поскольку вы не назначаете по ссылке, если условие ложно, лучшим вариантом, по-видимому, является:
$x = isset($_SESSION['foo']) ? $x = amp;$_SESSION['foo'] : false;
Комментарии:
1. Это помогло мне обойти эту проблему: twitter.com/LorenzoStanco/status/615507406626402304
2. Другим вариантом вашего последнего примера является:
(isset($_SESSION['foo']) ? $x = amp;$_SESSION['foo'] : $x = false);
Ответ №2:
Простой ответ: нет. Вам придется проделать долгий путь с if/else. Также было бы редкостью и, возможно, сбивало бы с толку, если бы в один раз была ссылка, а в следующий-значение. Я бы счел это более интуитивным, но опять же, я, конечно, не знаю вашего кода:
if(!isset($_SESSION['foo'])) $_SESSION['foo'] = false;
$x = amp;$_SESSION['foo'];
Что касается причины: понятия не имею, вероятно, это связано с тем, с какой точки зрения синтаксический анализатор рассматривает что-то как копию ценности или создание ссылки, которая таким образом не может быть определена в момент анализа.
Комментарии:
1. Как говорится в документации PHP :
Note: Please note that the ternary operator is a statement, and that it doesn't evaluate to a variable, but to the result of a statement. This is important to know if you want to return a variable by reference.
Ответ №3:
Давайте попробуем:
$x =amp; true?$y:$x;
Ошибка синтаксического анализа: синтаксическая ошибка, неожиданное "?", ожидание ввода T_PAAMAYIM_NEKUDOTAYIM...
$x = true?amp;$y:amp;$x;
Ошибка синтаксического анализа: синтаксическая ошибка, неожиданный ввод"amp;"...
Так что, как видите, он даже не разбирается. Виккен, вероятно, прав в том, почему это запрещено.
Вы можете обойти это с помощью функции:
function amp;ternaryRef($cond, amp;$iftrue, amp;$iffalse=NULL) {
if ($cond)
return $iftrue;
else
return $iffalse;
}
$x = 4;
$a = amp;ternaryRef(true, $x);
xdebug_debug_zval('a');
$b = amp;ternaryRef(false, $x);
xdebug_debug_zval('b');
дает:
a:
(refcount=2, is_ref=1),int 4
b:
(refcount=1, is_ref=0),null
Ответ №4:
К сожалению, вы не можете.
$x=false;
if (isset($_SESSION['foo']))
$x=amp;$_SESSION['foo'];
Ответ №5:
Комментарий к этому сообщению об ошибке может пролить некоторый свет на проблему:
http://bugs.php.net/bug.php?id=53117.
По сути, две проблемы с попыткой назначить ссылку из результата тернарного оператора заключаются в том, что:
- Выражения не могут давать ссылки, и
$x = (expression)
не является ссылочным назначением, даже если(expression)
является ссылкой (которой не является; см. пункт 1).