Koaleszenzfunktion für PHP?


131

Viele Programmiersprachen haben eine coalesce Funktion (kehrt der erste Nicht-NULL - Wert, beispielsweise ). PHP im Jahr 2009 leider nicht.

Was wäre ein guter Weg, um eine in PHP zu implementieren, bis PHP selbst eine Koaleszenzfunktion erhält?


11
Verwandte: der neue Null-Koaleszenz-Operator ?? für PHP 7.
Kojiro

Weitere Informationen zum Null-Koaleszenz-Operator finden Sie hier - stackoverflow.com/questions/33666256/…
Peter

1
Nur zu beachten, PHP7 implementiert diese Funktion
Grzegorz

@Grzegorz: Ein Operator ist keine Funktion, oder wo haben Sie diese Funktion neu in PHP 7 gefunden;)
hakre

Mit Funktion meinte ich nicht Funktion;) Merkmal. Ich war nicht genau. Vielen Dank :)
Grzegorz

Antworten:


194

Es gibt einen neuen Operator in PHP 5.3, der dies tut: ?:

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

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

// B
echo false ?: 'B';

// B
echo null ?: 'B';

Quelle: http://www.php.net/ChangeLog-5.php#5.3.0


25
Was ist mit mehreren ternären Verknüpfungen? Würde so etwas wie "echo $ a ?: $ B ?: $ C ?: $ D;" Arbeit?
ChrisR

5
Funktioniert nicht wie erwartet für Arrays. Wenn Sie beispielsweise versuchen zu überprüfen, ob ein undefiniertes Array-Element falsch ist, führt dies zu einem Fehler. $input['properties']['range_low'] ?: '?'
Keyo

5
Unabhängig von der Verwendung des Koaleszenzoperators sollten Sie einen Hinweis zum undefinierten Index erhalten.
Kevin

2
Mehrere Falsey-Argumente geben das letzte Argument array() ?: null ?: falsezurück false. Der Bediener ist in der Tat gesund.
Brad Koch

6
Beachten Sie, dass dies nicht nur eine Nicht-Null-Verschmelzung in anderen Sprachen akzeptiert, sondern jeden Wert, der implizit in einen Booleschen Wert konvertiert wird.
Stellen

65

PHP 7 führte einen echten Koaleszenzoperator ein :

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

Wenn der Wert vor dem ??nicht existiert oder nullder Wert nach dem ??ist.

Die Verbesserung gegenüber dem genannten ?:Operator besteht darin, dass der ??auch undefinierte Variablen behandelt, ohne eine zu werfen E_NOTICE.


Endlich nicht mehr isset () und empty () überall!
George Kagan

7
@timeNomad, das Sie noch benötigen, ist leer, es prüft nur auf Null
Nabeel Khan

Der einzige Weg, um sicheres "Falsy-Coalesce" zu bekommen, besteht darin, ein bisschen von beidem zu verwenden:($_GET['doesNotExist'] ?? null) ?: 'fallback'
Nathan Baulch

Der Vorteil von ?:over ??ist jedoch, dass auch leere Werte zusammengeführt werden, was ??nicht der Fall ist. Ähnlich wie das Verhalten des logischen ODER-Operators in JavaScript (dh $val || 'default') würde ?:ich eine praktischere Form der Verschmelzung finden, wenn wir in unserer Praxis letztendlich feststellen, dass wir sowohl leer als auch null auf die gleiche Weise behandeln (dh $val ?: 'default'). Und wenn Sie das Problem weiter forcieren und schlucken möchten E_NOTICE, können Sie dies sogar argumentieren:echo @$val ?: 'default';
Matt Borja

29

Erster Treffer für "PHP Coalesce" bei 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
Speichern Sie ein kleines Stück RAM und duplizieren Sie die Argumente nicht in ein Array. Führen Sie einfach foreach (func_get_args () als $ arg) {}
TravisO

17
@ [Alfred, Ciaran] - du bist falsch. foreach () wertet das erste Argument nur einmal aus, um ein Array zu erhalten, und iteriert dann darüber.
Gahooa

6
Das Einfügen von func_get_args () in foreach (hier als $ arg) ändert aus Sicht der Leistung nichts.
Savageman

7
@ Savageman ... genau ... wenn Sie daran denken, diese Millisekunde Leistung oder einige Bytes Speicher aus Ihrer Anwendung herauszuholen, sehen Sie wahrscheinlich den falschen Leistungs- / Speicherengpass
ChrisR

4
Ironischerweise ist dies jetzt der erste Hit für "PHP Coalesce" bei Google.
Will Shaver

18

Ich mag den ?: Operator wirklich. Leider ist es in meiner Produktionsumgebung noch nicht implementiert. Also benutze ich das Äquivalent dazu:

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

1
Dies ist eine 'wahrheitsgemäße' Verschmelzung, bei der mit array_filter alles entfernt wird, was in den n übergebenen Argumenten als falsch (einschließlich null) ausgewertet wird. Meine Vermutung, Shift anstelle des ersten Elements im Array zu verwenden, ist irgendwie robuster, aber das ist irgendwie robuster Teil weiß ich nicht. siehe: php.net/manual/en/…
Adam Tolley

3
Ich mag es, muss aber @hakre zustimmen - coalescesoll das erste Nicht-Null- Argument zurückgeben, auf das es stößt, einschließlich FALSE. Diese Funktion wird jedoch verworfen FALSE, wahrscheinlich nicht das, was op im Sinn hat (zumindest nicht das, was ich von einer coalesceFunktion erwarten würde ).
Madbreaks

1
Nur Variablen sollten als Referenz übergeben werden
Ben Sinclair

9

Es ist erwähnenswert, dass aufgrund der Behandlung nicht initialisierter Variablen und Array-Indizes durch PHP jede Art von Koaleszenzfunktion von begrenztem Nutzen ist. Ich würde gerne dazu in der Lage sein:

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

In den meisten Fällen führt dies jedoch zu einem PHP-Fehler mit einem E_NOTICE. Der einzig sichere Weg, die Existenz einer Variablen vor ihrer Verwendung zu testen, besteht darin, sie direkt in empty () oder isset () zu verwenden. Der von Kevin vorgeschlagene ternäre Operator ist die beste Option, wenn Sie wissen, dass alle Optionen in Ihrer Koaleszenz als initialisiert bekannt sind.


In diesem Fall funktionieren Array-Gewerkschaften ziemlich gut ( $getstuff = $_GET+$_SESSION+array('id'=>null);$id=$getstuff['id'];).
Brilliand

@Quill was soll das heißen? Haben Sie die vorgeschlagene Lösung mit Bezug?
Ben Sinclair

PHP 7 stellt den schönen neuen ternären Isset- Operator vor ??, um diese sehr häufige Operation präziser zu gestalten.
Botimer

6

Stellen Sie sicher, dass Sie genau angeben, wie diese Funktion mit bestimmten Typen funktionieren soll. PHP verfügt über eine Vielzahl von Typprüfungen oder ähnlichen Funktionen. Stellen Sie daher sicher, dass Sie wissen, wie diese funktionieren. Dies ist ein Beispielvergleich von is_null () und 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>';
}

Wie Sie sehen können, gibt empty () für alle diese Werte true zurück, is_null () jedoch nur für zwei von ihnen.


2

Ich erweitere die Antwort von Ethan Kent . Diese Antwort verwirft Nicht-Null-Argumente, die aufgrund der inneren Funktionsweise von array_filter als falsch ausgewertet werden. Dies ist coalescenormalerweise nicht die Funktion einer Funktion. Beispielsweise:

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

Hoppla

Um dies zu überwinden, sind ein zweites Argument und eine Funktionsdefinition erforderlich. Die aufrufbare Funktion gibt an, array_filterob der aktuelle Array-Wert zum Ergebnis-Array hinzugefügt werden soll oder nicht:

// "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'));
}

Es wäre schön, wenn Sie einfach weitergeben könnten issetoder 'isset'als 2. Argument array_filter, aber kein solches Glück.


0

Ich verwende dies derzeit, aber ich frage mich, ob es mit einigen der neuen Funktionen in PHP 5 nicht verbessert werden konnte.

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

0

PHP 5.3+, mit Verschlüssen:

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

Demo: https://eval.in/187365


Nur Variablen sollten als Referenz übergeben werden
Ben Sinclair

Ja, ich habe die strengen Regeln für die Demo gebrochen, nur um es einfach zu machen. :)
Paulo Freitas
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.