Можете ли вы передать ссылку при использовании тернарного оператора?

#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.

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

  1. Выражения не могут давать ссылки, и
  2. $x = (expression) не является ссылочным назначением, даже если (expression) является ссылкой (которой не является; см. пункт 1).