Ternární operátory v PHP (?:) - podmínka v jednom řádku

📅   26. 11. 2019
👤   Jan Barášek
Ternární operátor umožňuje zkrátit jednoduchou podmínku do jednoho řádku na místě, kde je rozepisování zbytečné, složité, nebo přímo nevhodné.

TL;DR

Ternární operátory jsou zkratkou pro if a else podmínky, proto je nemusíte používat. Hodí se pro stále se opakující kusy ověřovací logiky. Používejte formát (podmínka ? pozitivní logika : negativní logika) vždy včetně závorek. Používejte pro krátké ověření pro zpřehlednění a zkrácení kódu.

Základní definice

Často máme podmínku třeba ve tvaru:

$a = 5;
$b = 3;

if ($a > $b) {
     echo 'Je větší';
} else {
     echo 'Je menší';
}

Pokud tedy chceme vypsat jen jednu jednoduchou větu, musíme použít zbytečně 4 řádky kódu, což by šlo zkrátit na jeden.

$a = 5;
$b = 3;

echo 'Je ' . ($a > $b ? 'větší' : 'menší');

Obecně se ternární operátor zapisuje za pomoci 3 částí (proto se jmenuje "ternární"):

(podmínka ? pokud je pravda : pokud není pravda)

Ternární operátory se v praxi používají opravdu často, třeba k označení sudých řádků v tabulce:

$pole = [3, 1, 4, 1, 5, 9, 2];

for ($i = 0; $pole[$i]; $i++) {
     echo '<tr class="' . ($i % 2 ? 'odd' : 'even') . '">';

          // Tady se nějak pracuje s tabulkou...
          // třeba: echo '<td>' . $pole[$i] . '</td>';

     echo '</tr>';
}

Příklad použití ternárního operátoru

Docela často potřebujeme zkontrolovat existenci hodnoty nějaké proměnné a případně jí ihned použít. Pokud neexistuje, tak chceme vrátit defaultní hodnotu.

Klasickým přístupem se to řeší třeba takto:

$a = 5;
$b = 8;

$c = $a ? $a : $b;

Pokud existuje proměnná $a, použijte se jako hodnota $a, jinak $b.

Někdy však hodnotu získáváme z nějaké funkce:

$a = 5;
$b = 3;
$default = 42;

$c = funkce($a, $b) ? funkce($a, $b) : $default;

Tento způsob volání je velice neefektivní vzhledem k systémovým prostředkům. Nejprve se totiž musí funkce zavolat, a pokud existuje, tak se volá znovu, pro získání hodnoty, která se uloží do proměnné $c.

To by šlo lépe vyřešit přes pomocnou proměnnou:

$a = 5;
$b = 3;
$pomocnaPromenna = funkce($a, $b);
$default = 42;

$c = $pomocnaPromenna ? $pomocnaPromenna : $default;

Nevhodné použití

Ne vždy se ternární operátor vyplatí použít, protože při zápisu komplikovaných a vnořených podmínek způsobuje spíše zmatky.

Podívejte se sami na příklad:

$valid = true;
$lang = 'french';

$x = $valid
     ? ($lang === 'french' ? 'oui' : 'yes')
     : ($lang === 'french' ? 'non' : 'no');

Poznali byste na první pohled, že proměnná $x bude obsahovat hodnotu oui?

Po trochu cviku možná ano, ale to není ta správná odpověď. :)

Ověření (ne)existence hodnoty a použití výchozí

Největší sílu mají ternární operátory při rutinním ověřování (ne)existence hodnot a použití jiných výchozích.

Například chceme zjistit, jestli pro článek existuje jeho hlavní kategorie a pokud ne, tak vypsat náhradní hlášku:

echo $mainCategory ?? 'Kategorie neexistuje';

Operátor ?? (dva otazníky) ověří, jestli proměnná $mainCategory existuje a není null. Funguje stejně, jako funkce isset().

Ověření prázdnosti hodnoty

Velmi často se hodí konstrukce pro ověření, že výstupní hodnota není prázdná (tj. není null, 0, false nebo '' (prázdný string)).

To se dá zapsat takto:

$a = 5;
$b = 3;
$default = 42;

$c = funkce($a, $b) ?: $default;

Nejprve se zavolá funkce($a, $b), poté se otestuje její hodnota a když není prázdná, tak se ihned předá do proměnné $c, jinak bude použita proměnná $default.

Operátor ?: funguje jako operátor != v podmínce (nepravda bez ohledu na datový typ) a zapamatovat se dá třeba tak, že vypadá jako smajlík s vlasy Elvise.

Podpora starších verzí PHP

Operátor ?: funguje od PHP 7. Ve starších verzí si musíme vystačit s podmínkou if (...), kterou lze docílit stejného chování. Nezapomínejte na to, že ternární operátory jsou ve skutečnosti jen zkratka k zápisu toho samého, co se řeší podmínkami.

Neexistence hodnoty lze ověřit funkcí isset(), která kontroluje, že proměnná existuje a není prázdná (null).

Místo kódu:

$a = 5;
$b = 3;

$c = $a ?? $b;

Potom zapíšeme starší alternativu:

$a = 5;
$b = 3;

$c = isset($a) && $a ?? $b;

Upozornění: Na pořadí isset() a samotné proměnné záleží. Pokud bychom pořadí otočili a proměnná neexistovala, tak by se vyvolala chyba přístupu do neexistující proměnné.

Jan Barášek     Více o autorovi

Autor článku pracuje jako seniorní vývojář a software architekt v Praze. Navrhuje a spravuje velké webové aplikace, které znáte a používáte. Od roku 2009 nabral bohaté zkušenosti, které tímto webem předává dál.

Rád vám pomůžu:

Kontakt Spolupráce