Вопрос по php – Объединить функцию для PHP?

125

Многие языки программирования имеют функцию объединения (возвращает первое ненулевое значение,пример). PHP, к сожалению, в 2009 году нет.

Что было бы хорошим способом реализовать его в PHP, пока сам PHP не получит функцию объединения?

Связанный: новыйnull coalescing operator ?? для PHP 7. kojiro
Под функцией я не имел в виду функцию;) Я не был точен. Спасибо :) Grzegorz
@Grzegorz: оператор не является функцией, или где вы нашли эту функцию новой в PHP 7;) hakre
Больше информации об операторе слияния null можно найти здесь -stackoverflow.com/questions/33666256/… Peter
Просто чтобы заметить, PHP7 реализовал эту функцию Grzegorz

Ваш Ответ

9   ответов
29

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

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

@[Alfred,Ciaran] - you are incorrect. foreach() evaluates the first argument only once, to get an array, and then iterates over it. – gahooa Dec 12 '09 at 1:34
Помещение func_get_args () в foreach (здесь как $ arg) ничего не изменит с точки зрения производительности.
По иронии судьбы, это первый хит для «php coalesce». в гугле
@Savageman ... точно ... если вы думаете о том, чтобы выжать из приложения эту миллисекунду производительности или несколько байтов памяти, вы, вероятно, видите неправильное узкое место производительности / памяти
Сохраните чуть-чуть оперативной памяти и не дублируйте аргументы в массив, просто выполните foreach (func_get_args () как $ arg) {}
9

что из-за обработки PHP неинициализированных переменных и индексов массивов любая функция слияния имеет ограниченное применение. Я хотел бы быть в состоянии сделать это:

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

Но это в большинстве случаев приведет к ошибке PHP с E_NOTICE. Единственный безопасный способ проверить существование переменной перед ее использованием - это использовать ее непосредственно в empty () или isset (). Тернарный оператор, предложенный Кевином, является наилучшим вариантом, если вы знаете, что все параметры в вашей коалиции известны как инициализированные.

PHP 7 представляет прекрасный новыйisset ternary оператор?? чтобы сделать эту очень распространенную операцию более краткой.
@ Что это должно значить? Вы предложили решение со ссылкой?
Вот что они здесь делаютcodereview.stackexchange.com/a/40323/81342
В этом случае объединения массивов работают довольно хорошо ($getstuff = $_GET+$_SESSION+array('id'=>null);$id=$getstuff['id'];).
@ Энди, этот пост в Code Review не по теме ...
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>';
}

Как вы можете видеть, empty () возвращает true для всех из них, но is_null () делает это только для 2 из них.

2

Итан Кент, Этот ответ отбрасывает ненулевые аргументы, которые оцениваются как ложные из-за внутренней работыarray_filterчто не являетсяcoalesce функция обычно делает. Например:

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

Oops

Чтобы преодолеть это, требуется второй аргумент и определение функции.callable функция отвечает за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, но не такая удача.

60

оператор объединения:

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

Если значение до?? не существует или являетсяnull значение после?? взят.

Улучшение по сравнению с упомянутым?: оператор, что?? также обрабатывает неопределенные переменные, не бросаяE_NOTICE.

@timeNomad вам все еще нужно пусто, он проверяет только на ноль
Единственный способ обезопасить себя от «ложного слияния» это использовать немного из обоих:($_GET['doesNotExist'] ?? null) ?: 'fallback'
Наконец, больше нет isset () и empty () повсюду!
0

function coalesce()
{
    return array_shift(array_filter(func_get_args(), function ($value) {
        return !is_null($value);
    }));
}

Демо-версия:https://eval.in/187365

Только переменные должны быть переданы по ссылке
Да, я нарушил строгие правила для демонстрации, просто чтобы сделать это простым. :)
182

?:

// 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

Я только что проверил это, и это действительно работает. Хорошее предложение.
Не работает, как ожидалось для массивов. Например, при попытке проверить, равен ли неопределенный элемент массива значению Falsey, вы получите ошибку.$input['properties']['range_low'] ?: '?'
Имейте в виду, что это не просто принимает ненулевое, как объединение в других языках, но любое значение, которое будет неявно преобразовано в логическое значение. Поэтому убедитесь, что вы освежите своиtype casting rules
А как насчет нескольких троичных ярлыков, что-то вроде "echo $ a?: $ B?: $ C?: $ D; & quot;" Работа?
Вы должны получить уведомление о неопределенном индексе независимо от использования оператора coalesce.
0

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

function coalesce() {
  $args = func_get_args();
  foreach ($args as $arg) {
    if (!empty($arg)) {
    return $arg;
    }
  }
  return $args[0];
}
пусто не NULL.
18

К сожалению, это еще не реализовано в моей производственной среде. Поэтому я использую эквивалент этого:

function coalesce() {
  return array_shift(array_filter(func_get_args()));
}
ложь не NULL.
Только переменные должны быть переданы по ссылке
это "правда" coalesce, используя array_filter, чтобы избавиться от всего, что оценивается как false (включая null) в переданных n аргументах. Я предполагаю, что использование shift вместо первого элемента в массиве как-то более надежно, но эту часть я не знаю , увидеть:php.net/manual/en/…
Мне это нравится, но я должен согласиться с @hakre -coalesce должен вернуть первыйnon-null аргумент, который он встречает, который будет включать в себяFALSE, Эта функция откажетсяFALSE хотя, вероятно, не то, что имеет в виду опера (по крайней мере, не то, что я хотел бы изcoalesce функция).
нечитабельно, но очень лаконично, мило.

Похожие вопросы