Функція злиття для PHP?


131

Багато мов програмування мають функцію з'єднання (повертає перше не-NULL значення, наприклад ). PHP, на жаль у 2009 році, ні.

Який був би хороший спосіб впровадити його в PHP, поки PHP сам не отримає функцію злиття?


11
Пов’язано: новий оператор ?? з нульовим згортанням для PHP 7.
kojiro

Більше інформації про оператора null coalesce можна знайти тут - stackoverflow.com/questions/33666256/…
Пітер

1
Зауважимо, PHP7 реалізував цей вимисел
Гжегож

@Grzegorz: Оператор - це не функція, або де ти знайшов цю функцію новою в PHP 7;)
hakre

Під функцією я не мав на увазі функцію;) Особливість. Я не був точним. Дякую :)
Grzegorz

Відповіді:


194

У php 5.3 є новий оператор, який робить це: ?:

// A
echo 'A' ?: 'B';

// B
echo '' ?: 'B';

// B
echo false ?: 'B';

// B
echo null ?: 'B';

Джерело: http://www.php.net/ChangeLog-5.php#5.3.0


25
А як щодо кількох потрійних ярликів, щось на зразок "echo $ a?: $ B?: $ C?: $ D;" робота?
ChrisR

5
Не працює, як очікувалося для масивів. Наприклад, при спробі перевірити, чи не визначений елемент масиву є фальсі, це призведе до помилки. $input['properties']['range_low'] ?: '?'
Кейо

5
Ви повинні отримати повідомлення про невизначений індекс незалежно від використання оператора coalesce.
Кевін

2
Кілька аргументів фальси повертають останній аргумент, array() ?: null ?: falseповертають false. Оператор справді здоровий.
Бред Кох

6
Майте на увазі, що це сприймає не просто нульове, як coalesce іншими мовами, а будь-яке значення, яке буде неявно перетворене в булеве. Тож переконайтеся, що ви
дотримуєтесь

65

PHP 7 представив справжнього оператора з'єднання :

echo $_GET['doesNotExist'] ?? 'fallback'; // prints 'fallback'

Якщо значення до ??цього не існує, або це nullзначення після ??взяття.

Поліпшенням у порівнянні згаданим ?:оператором є те, що ??також обробляє невизначені змінні без викидання an E_NOTICE.


Нарешті, більше не є (і) порожнім () повсюди!
Джордж Каган

7
@timeNomad вам все одно знадобиться порожній, він перевіряє лише нуль
Nabeel Khan

Єдиний спосіб отримати безпечний "фальшивий злиття" - використовувати трохи обох:($_GET['doesNotExist'] ?? null) ?: 'fallback'
Натан Баулч,

Перевага ?:над ??, однак, полягає в тому, що він також поєднує порожні значення, що ??не робить. Аналогічно поведінці логічного оператора АБО у JavaScript (тобто $val || 'default'), я вважаю ?:б більш практичною формою з’єднання, якщо в нашій практиці ми в кінцевому підсумку виявляємо, що обробляємо як порожні, так і нульові однаково (тобто $val ?: 'default'). І якщо ви хочете ще більше змусити проблему і проковтнути E_NOTICE, ви можете це навіть аргументувати:echo @$val ?: 'default';
Метт Борджа

29

Перший хіт для "php coalesce" на Google.

function coalesce() {
  $args = func_get_args();
  foreach ($args as $arg) {
    if (!empty($arg)) {
      return $arg;
    }
  }
  return NULL;
}

http://drupial.com/content/php-coalesce


9
Збережіть крихітний таран і не дублюйте аргументи в масив, просто зробіть передбачення (func_get_args () як $ arg) {}
TravisO

17
@ [Альфред, Ціаран] - ви неправі. foreach () оцінює перший аргумент лише один раз, щоб отримати масив, а потім повторює його.
gahooa

6
Якщо розмістити func_get_args () всередині foreach (тут як $ arg), нічого не зміниться з точки зору продуктивності.
Савагеман

7
@Savageman ... саме ... якщо ви думаєте видавити цю мілісекундну продуктивність або кілька байт пам'яті зі свого додатку, ви, мабуть, дивитесь на неправильну ефективність / вузьке місце пам’яті
ChrisR

4
Як не дивно, це зараз перший хіт для "php coalesce" в Google.
Буде Шавер

18

Мені дуже подобається оператор ?:. На жаль, вона ще не реалізована в моєму виробничому середовищі. Тому я використовую аналог цього:

function coalesce() {
  return array_shift(array_filter(func_get_args()));
}

1
це "truthy" злиття, використовуючи array_filter, щоб позбутися від усього, що оцінюється як false (включаючи null) в n переданих аргументах. Я здогадуюсь, що використання shift замість першого елемента в масиві якимось надійнішим, але це частина я не знаю. дивіться: php.net/manual/en/…
Адам Толлі

3
Мені це подобається, але треба погодитися з @hakre - coalesceповинен повернути перший ненульовий аргумент, який він зустрічає, який би включав FALSE. Ця функція буде відкинута FALSE, мабуть, не те, що має на увазі оп (принаймні, не те, що я хотів би вийти з coalesceфункції).
Madbreaks

1
Посилаються лише змінні
Ben Sinclair

9

Варто зазначити, що завдяки обробці PHP неініталізованими змінними та індексами масиву будь-який вид злиття функції має обмежене використання. Мені б хотілося це зробити:

$id = coalesce($_GET['id'], $_SESSION['id'], null);

Але це в більшості випадків призведе до помилки PHP з E_NOTICE. Єдиний безпечний спосіб перевірити існування змінної перед її використанням - це використовувати її безпосередньо в порожній () або isset (). Тернарний оператор, запропонований Кевіном, є найкращим варіантом, якщо ви знаєте, що всі варіанти вашої спільної передачі, як відомо, ініціалізовані.


У цьому випадку об'єднання масивів працюють досить непогано ( $getstuff = $_GET+$_SESSION+array('id'=>null);$id=$getstuff['id'];).
Brilliand

@Quill, що це повинно означати? Ви пропонували рішення із посиланням?
Бен Сінклер

PHP 7 представляє чудовий новий трисезонний оператор, ??щоб зробити цю дуже поширену операцію більш стислою.
ботимер

6

Переконайтесь, що ви точно визначили, як ви хочете, щоб ця функція працювала з певними типами. PHP має широкий спектр функцій перевірки типу або подібних функцій, тому переконайтеся, що ви знаєте, як вони працюють. Це приклад порівняння is_null () та empty ()

$testData = array(
  'FALSE'   => FALSE
  ,'0'      => 0
  ,'"0"'    => "0"  
  ,'NULL'   => NULL
  ,'array()'=> array()
  ,'new stdClass()' => new stdClass()
  ,'$undef' => $undef
);

foreach ( $testData as $key => $var )
{
  echo "$key " . (( empty( $var ) ) ? 'is' : 'is not') . " empty<br>";
  echo "$key " . (( is_null( $var ) ) ? 'is' : 'is not')  . " null<br>";
  echo '<hr>';
}

Як бачите, порожній () повертає істину для всіх цих, але is_null () робить це лише для двох з них.


2

Я розкриваю відповідь, яку опублікував Етан Кент . Ця відповідь відкине ненульові аргументи, які оцінюються як хибні завдяки внутрішній роботі array_filter , що не є тим, що coalesceфункція зазвичай виконує. Наприклад:

echo 42 === coalesce(null, 0, 42) ? 'Oops' : 'Hooray';

На жаль

Для подолання цього потрібен другий аргумент та визначення функції. Функція дзвінка відповідає за те, array_filterчи потрібно додавати поточне значення масиву до масиву результатів:

// "callable"
function not_null($i){
    return !is_null($i);  // strictly non-null, 'isset' possibly not as much
}

function coalesce(){
    // pass callable to array_filter
    return array_shift(array_filter(func_get_args(), 'not_null'));
}

Було б добре, якби ви могли просто передати issetабо 'isset'як другий аргумент array_filter, але такої удачі немає.


0

Зараз я цим користуюся, але мені цікаво, чи не вдалось би його покращити за допомогою деяких нових функцій PHP 5.

function coalesce() {
  $args = func_get_args();
  foreach ($args as $arg) {
    if (!empty($arg)) {
    return $arg;
    }
  }
  return $args[0];
}

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.