Более сжатое тернарное выражение?

Мне часто приходится писать код со следующим логическим шаблоном:

$foo = isset($bar) ? $bar : $baz; 

Я знаю о синтаксисе ?: ::

 $foo = $bar ?: $baz; 

… который, на первый взгляд, кажется тем, что я ищу; тем не менее, он выдает неопределенный индекс уведомлений, когда $bar не установлен. Он также использует ту же логику, что и empty() , что означает, что «пустые» значения, такие как FALSE , 0 , "0" и т. Д., Не проходят. Следовательно, это не совсем эквивалентно.

Есть ли более короткий способ написания этого кода, не бросая уведомление, когда $bar не установлен?

Редактировать:

Чтобы сделать это более понятным, почему я ищу синтаксис ярлыков, вот лучший пример:

 $name = isset($employee->getName()) ? $employee->getName() : '<unknown>'; 

В этом случае $employee может быть объектом из сторонней библиотеки, и может быть допустимым сценарием, что его name может быть NULL . Я хотел бы установить переменную $name в возвращаемое имя (если оно есть), но некоторые разумные значения по умолчанию, если их нет.

Если вызов метода более сложный, чем просто геттер, то пример становится еще более подробным, так как мы должны кэшировать результат:

 $bar = $some->reallyExpensiveOperation(); $foo = isset($bar) ? $bar : $baz; 

Я бы использовал только синтаксис короткой руки, когда вы явно предопределяете свои переменные или используете объект с магическим геттером. Это очень простой пример того, где я обычно использовал бы краткий синтаксис тройной руки

 class Foo { public function __get($name) { return isset($this->{$name}) ? $this->{$name} : ''; } } $foo = new Foo(); $bar = $foo->baz ?: 'default'; 

Используя оператор управления ошибками, вы можете технически сократить его до:

 $foo = @$bar ?: $baz; 

Если $bar не установлен, значение принимает значение null, и вы не получаете уведомления об ошибке, так как вы подавили ошибку. Некоторые, однако, могут не одобрить этот код, так как его не очень удобно использовать @ поскольку он маскирует ошибки и затрудняет отладку.

Без этого я не верю, что есть более короткая нотация, использующая isset .

Edit: Как отмечено @drrcknlsn, это не будет работать, если переменные являются false или 0 или даже null , поэтому мне кажется, что избежать вызова isset .

Когда $bar не определен, на самом деле не существует «более короткого» способа написать тот же код.

Есть два, что я считаю «хаками» для этого, однако они также могут влиять на другие вещи:

  1. Ошибка дросселирования с помощью @ , например $foo = @$bar ?: $baz; будет делать именно то, что вы хотите, и дросселировать неопределенную ошибку, которая возникает, когда $bar не определен. Если он определен, он также будет работать по желанию. Однако недостатком является то, что @ может снизить эффективность вашего кода, если он используется повторно.
  2. Отключение уведомлений с помощью error_reporting(E_ALL & ~E_NOTICE); , Это все равно будет отображать все регулярные ошибки, но только не уведомления, которые будут эффективно скрывать ошибку «variable is undefined». Недостатком этого является то, что вы не увидите никаких других уведомлений.

Теперь, мое обязательное личное мнение, я бы посоветовал продолжать писать его в полном объеме. Тернарный оператор уже сокращен, эффективно сокращая:

 if (isset($bar)) { $foo = $bar; } else { $foo = $baz; } 

в гораздо более короткие сроки

 $foo = isset($bar) ? $bar : $baz; 

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

UPDATE: для поддержки вашего редактирования, где вы назначаете $bar возвращаемому значению функции, а затем $foo основывается на нем, вы можете комбинировать операторы в одну строку:

 $foo = (($bar = $some->reallyExpensiveOperation()) != null) ? $bar : $baz; 

Это почти такая же длина кода, как и две строки, но здесь она также может быть немного сокращена. Например, если значение null не является единственным значением, которое вы считаете «недействительным», но значение false также считается, вы можете полностью удалить значение != null и разрешить условие рассматривать как простое логическое значение:

 $foo = ($bar = $some->reallExpensiveOperation()) ? $bar : $baz; 

В этом примере $bar по-прежнему доступна после тройной операции (т. Е. – она ​​не теряет область видимости), поэтому, если вам не нужна предварительная обработка этой переменной, нет большого недостатка в этом методе, кроме чтения ,