2010-12-01 2 views
18

Для очень общего случая присвоения значения переменной на основе результата выражения я фанат троичных операторов:Условно назначая PHP значения

$foo = $bar ? $a : b; 

Однако, если $ бар является относительно дорогостоящая операция, и я хочу, чтобы присвоить результат $ бара до $ Foo, если результат truthy, это неэффективно:

$foo = SomeClass::bigQuery() ? SomeClass::bigQuery() : new EmptySet(); 

Один из вариантов:

$foo = ($result = SomeClass::bigQuery()) ? $result : new EmptySet(); 

Но я бы предпочел не иметь дополнительные $result сидя в памяти.

Самый лучший вариант, у меня есть:

$foo = ($foo = SomeClass::bigQuery()) ? $foo : new EmptySet(); 

Или без тройных операторов:

if(!$foo = SomeClass::bigQuery()) $foo = new EmptySet(); 

Или, если операторы потока программы не ваш стиль:

($foo = SomeClass::bigQuery()) || ($foo = new EmptySet()); 

Так много вариантов, не из них действительно удовлетворительные. Что бы вы использовали, и я пропустил что-то действительно очевидное здесь?

ответ

33

PHP 5.3 введен новый синтаксис для решения именно этой проблемы:

$x = expensive() ?: $default; 

ВИДЕТЬ documentation:

Начиная с PHP 5.3, можно выйти из средней части троичного оператора ,
Выражение expr1 ?: expr3 возвращает expr1, если expr1 оценивает по TRUE и expr3 в противном случае.

+1

Я лично избежать PHP 5.3-только синтаксис , и предпочитают `$ x = дорогой(); если (!$ x) $ x = $ default; ` – meagar 2010-12-01 22:22:20

+0

Wow; Я просто собирался прокомментировать: «PHP нуждается в [расширении GNU для тройников] (http://stackoverflow.com/questions/3319075/ternary-conditional-operator-behaviour-when-leaving-one-expression-empty)» – 2010-12-01 22:23:10

+0

ах-ха - пропустил это в руководстве. Я предполагаю, что это означает, что нет лучшего метода для 5.2.x (который я должен поддерживать в среднесрочной перспективе)? – Hamish 2010-12-01 22:45:47

8

Можете ли вы обновить SomeClass: bigQuery(), чтобы вернуть новый EmptySet() вместо false?

Тогда вы просто

$foo = SomeClass::bigQuery(); 
1
$foo = SomeClass::bigQuery(); 
if (!$foo) $foo = new EmptySet(); 

Revision два, кредит @meagar

1

Небольшое изменение вашего последнего варианта:

$ Foo = SomeClass :: BigQuery() или новый EmptySet(); Это не работает, спасибо, что заметили.

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

$result = mysql_query($sql) or die(mysql_error()); 

Хотя лично я предпочитаю тот, который вы уже упоминали:

if(!$foo = SomeClass::bigQuery()) 
    $foo = new EmptySet(); 
Смежные вопросы