Oc-windows.ru

IT Новости из мира ПК
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Php null coalescing operator

PHP ternary operator vs null coalescing operator

Can someone explain the differences between ternary operator shorthand ( ?: ) and null coalescing operator ( ?? ) in PHP?

When do they behave differently and when in the same way (if that even happens)?

13 Answers 13

When your first argument is null, they’re basically the same except that the null coalescing won’t output an E_NOTICE when you have an undefined variable. The PHP 7.0 migration docs has this to say:

The null coalescing operator (??) has been added as syntactic sugar for the common case of needing to use a ternary in conjunction with isset(). It returns its first operand if it exists and is not NULL; otherwise it returns its second operand.

Here’s some example code to demonstrate this:

The lines that have the notice are the ones where I’m using the shorthand ternary operator as opposed to the null coalescing operator. However, even with the notice, PHP will give the same response back.

Of course, this is always assuming the first argument is null . Once it’s no longer null, then you end up with differences in that the ?? operator would always return the first argument while the ?: shorthand would only if the first argument was truthy, and that relies on how PHP would type-cast things to a boolean.

would then have $a be equal to false and $b equal to ‘g’ .

If you use the shortcut ternary operator like this, it will cause a notice if $_GET[‘username’] is not set:

So instead you have to do something like this:

The null coalescing operator is equivalent to the above statement, and will return ‘default’ if $_GET[‘username’] is not set or is null :

Note that it does not check truthiness. It checks only if it is set and not null.

You can also do this, and the first defined (set and not null ) value will be returned:

Now that is a proper coalescing operator.

Ran the below on php interactive mode ( php -a on terminal). The comment on each line shows the result.

So this is my interpretation:

1. The Null Coalescing Operator — ?? :

  • ?? is like a «gate» that only lets NULL through.
  • So, it always returns first parameter, unless first parameter happens to be NULL.
  • This means ?? is same as ( !isset() || is_null() )

2. The Ternary Operator — ?:

  • ?: is like a gate that lets anything falsy through — including NULL
  • 0 , empty string , NULL , false , !isset() , empty() .. anything that smells falsy
  • Just like the classic ternary operator: echo ($x ? $x : false)
  • NOTE: ?: will throw PHP NOTICE on undefined ( unset or !isset() ) variables

3. So doctor, when do I use ?? and ?: ..

  • I’m only joking — I’m not a doctor and this is just an interpretation
  • I would use ?: when
    • doing empty($x) checks
    • Classic ternary operation like !empty($x) ? $x : $y can be shortened to $x ?: $y
    • if(!$x) < fn($x); >else < fn($y); >can be shortened to fn(($x ?: $y))
  • I would use ?? when
    • I want to do an !isset() || is_null() check
    • e.g check if an object exists — $object = $object ?? new objClassName();

4. Stacking operators .

Ternary Operator can be stacked .

This is basically a sequence of:

Null Coalese Operator can be stacked .

This is a sequence of:

Using stacking, I can shorten this:

To this:

The major difference is that

Ternary Operator expression expr1 ?: expr3 returns expr1 if expr1 evaluates to TRUE but on the other hand Null Coalescing Operator expression (expr1) ?? (expr2) evaluates to expr1 if expr1 is not NULL

Ternary Operator expr1 ?: expr3 emit a notice if the left-hand side value (expr1) does not exist but on the other hand Null Coalescing Operator (expr1) ?? (expr2) In particular, does not emit a notice if the left-hand side value (expr1) does not exist, just like isset() .

TernaryOperator is left associative

Null Coalescing Operator is right associative

Now lets explain the difference between by example :

Ternary Operator (?:)

Null Coalescing Operator (??)

Here is the table that explain the difference and similarity between ‘??’ and ?:

Special Note : null coalescing operator and ternary operator is an expression, and that it doesn’t evaluate to a variable, but to the result of an expression. This is important to know if you want to return a variable by reference. The statement return $foo ?? $bar; and return $var == 42 ? $a : $b; in a return-by-reference function will therefore not work and a warning is issued.

Both of them behave differently when it comes to dynamic data handling.

If the variable is empty ( » ) the null coalescing will treat the variable as true but the shorthand ternary operator won’t. And that’s something to have in mind.

Both are shorthands for longer expressions.

?: is short for $a ? $a : $b . This expression will evaluate to $a if $a evaluates to TRUE.

?? is short for isset($a) ? $a : $b . This expression will evaluate to $a if $a is set and not null.

Their use cases overlaps when $a is undefined or null. When $a is undefined ?? will not produce an E_NOTICE, but the results are the same. When $a is null the result is the same.

For the beginners:

Null coalescing operator (??)

Everything is true except null values and undefined (variable/array index/object attributes)

this is basically check the variable(array index, object attribute.. etc) is exist and not null . similar to isset function

Ternary operator shorthand (?:)

every false things ( false , null , 0 ,empty string) are come as false, but if it’s a undefined it also come as false but Notice will throw

Hope this helps

Scroll down on this link and view the section, it gives you a comparative example as seen below:

However, it is not advised to chain the operators as it makes it harder to understand the code when reading it later on.

The null coalescing operator (??) has been added as syntactic sugar for the common case of needing to use a ternary in conjunction with isset(). It returns its first operand if it exists and is not NULL; otherwise it returns its second operand.

Essentially, using the coalescing operator will make it auto check for null unlike the ternary operator.

Читать еще:  Проверить пунктуационные ошибки

The other answers goes deep and give great explanations. For those who look for quick answer,

$a ?: ‘fallback’ is $a ? $a : ‘fallback’

$a ?? ‘fallback’ is $a = isset($a) ? $a : ‘fallback’

The main difference would be when the left operator is either:

  • A falsy value that is NOT null ( 0 , » , false , [] , . )
  • An undefined variable

It seems there are pros and cons to using either ?? or ?: . The pro to using ?: is that it evaluates false and null and «» the same. The con is that it reports an E_NOTICE if the preceding argument is null. With ?? the pro is that there is no E_NOTICE, but the con is that it does not evaluate false and null the same. In my experience, I have seen people begin using null and false interchangeably but then they eventually resort to modifying their code to be consistent with using either null or false, but not both. An alternative is to create a more elaborate ternary condition: (isset($something) or !$something) ? $something : $something_else .

The following is an example of the difference of using the ?? operator using both null and false:

By elaborating on the ternary operator however, we can make a false or empty string «» behave as if it were a null without throwing an e_notice:

Personally, I think it would be really nice if a future rev of PHP included another new operator: 😕 that replaced the above syntax. ie: // $var = $false 😕 «true»; That syntax would evaluate null, false, and «» equally and not throw an E_NOTICE.

Php null coalescing operator

Объявления скалярных типов введена в двух вариантах: принудительный (по умолчанию) и строгий. Следующие типы могут использоваться для объявления параметров (в обоих вариантах): строки ( string ), целые (int), числа с плавающей точкой ( float ) и логические значения (bool). Они дополняют аргументы других типов, введенных в PHP 5: имена классов, интерфейсов, array и callable .

// Принудительный режим
function sumOfInts ( int . $ints )
<
return array_sum ( $ints );
>

var_dump ( sumOfInts ( 2 , ‘3’ , 4.1 ));

Результат выполнения данного примера:

Для установки строгого режима, в самом начале файла необходимо поместить одну директиву declare. Это означает, что строгость объявления скалярных типов работает на уровне файла и не затрагивает весь остальной код. Эта директива затрагивает не только объявления параметров, но и возвращаемые значения функций (см. объявления возвращаемого типа), встроенные функции PHP и функции загруженных расширений.

Подробную документацию и примеры использования читайте в разделе декларация типов.

Объявления возвращаемых значений

В PHP 7 добавлена поддержка объявления возвращаемого типа. Аналогично как и объявления типов аргументов, объявление типа возвращаемого значения указывает, значение какого типа должна вернуть функция. Для объявления типа возвращаемого значения доступны все те же типы, что и для объявления типов аргументов.

function arraysSum (array . $arrays ): array
<
return array_map (function(array $array ): int <
return array_sum ( $array );
>, $arrays );
>

print_r ( arraysSum ([ 1 , 2 , 3 ], [ 4 , 5 , 6 ], [ 7 , 8 , 9 ]));

Результат выполнения данного примера:

Полную документацию и примеры использования читайте в разделе про объявление возвращаемого типа.

Оператор объединения с null

Был добавлен оператор объединения с null (??), являющийся синтаксическим сахаром для достаточно распространенного действия, когда совместно используются тернарный оператор и функция isset() . Он возвращает первый операнд, если он задан и не равен NULL , а в обратном случае возвращает второй операнд.

// Извлекаем значение $_GET[‘user’], а если оно не задано,
// то возвращаем ‘nobody’
$username = $_GET [ ‘user’ ] ?? ‘nobody’ ;
// Это идентично следующему коду:
$username = isset( $_GET [ ‘user’ ]) ? $_GET [ ‘user’ ] : ‘nobody’ ;

// Данный оператор можно использовать в цепочке.
// В этом примере мы сперва проверяем, задан ли $_GET[‘user’], если нет,
// то проверяем $_POST[‘user’], и если он тоже не задан, то присваеваем ‘nobody’.
$username = $_GET [ ‘user’ ] ?? $_POST [ ‘user’ ] ?? ‘nobody’ ;
?>

Оператор spaceship (космический корабль)

Этот оператор предназначен для сравнения двух выражений. Он возвращает -1, 0 или 1 если $a , соответственно, меньше, равно или больше чем $b . Сравнение производится в соответствии с правилами сравнения типов PHP.

// Целые числа
echo 1 1 ; // 0
echo 1 2 ; // -1
echo 2 1 ; // 1

// Числа с плавающей точкой
echo 1.5 1.5 ; // 0
echo 1.5 2.5 ; // -1
echo 2.5 1.5 ; // 1

// Строки
echo «a» «a» ; // 0
echo «a» «b» ; // -1
echo «b» «a» ; // 1
?>

Определение констант массивов с помощью define()

Можно определить константу типа array с помощью функции define() . В PHP 5.6 такие константы можно было задавать только с помощью const.

echo ANIMALS [ 1 ]; // выводит «cat»
?>

Анонимные классы

Была добавлена поддержка анонимных классов с помощью new class. Их можно использовать тогда, когда нужен одноразовый класс и создавать полноценный класс, а потом его объект не имеет смысла:

interface Logger <
public function log ( string $msg );
>

class Application <
private $logger ;

public function getLogger (): Logger <
return $this -> logger ;
>

public function setLogger ( Logger $logger ) <
$this -> logger = $logger ;
>
>

$app = new Application ;
$app -> setLogger (new class implements Logger <
public function log ( string $msg ) <
echo $msg ;
>
>);

var_dump ( $app -> getLogger ());
?>

Результат выполнения данного примера:

Подробную документацию и примеры использования читайте в разделе про анонимные классы.

Синтаксис кодирования Unicode

Он принимает шестнадцатеричный код Unicode и записываем его в формате UTF-8 в двойных кавычках или формате heredoc. Любой корректный код будет принят. Ведущие нули по желанию.

Результат выполнения данного примера:

Closure::call()

Closure::call() является более производительным и коротким способом временного связывания области действия объекта с замыканием и его вызовом.

// До PHP 7
$getX = function() x ;>;
$getXCB = $getX -> bindTo (new A , ‘A’ ); // промежуточное замыкание
echo $getXCB ();

// PHP 7+
$getX = function() x ;>;
echo $getX -> call (new A );

Результат выполнения данного примера:

unserialize() с фильтрацией

Этот функционал обеспечивает более высокий уровень безопасности при десериализации объектов с непроверенными данными. Это позволяет предотвратить возможную инъекцию кода, позволяя разработчику использовать белый список классов для десериализации.

// Преобразование всех объектов в __PHP_Incomplete_Class
$data = unserialize ( $foo , [ «allowed_classes» => false ]);

// Преобразование всех объектов, кроме MyClass и MyClass2 в __PHP_Incomplete_Class
$data = unserialize ( $foo , [ «allowed_classes» => [ «MyClass» , «MyClass2» ]]);

// Поведение по умолчанию принимает все классы (можно просто не задавать второй аргумент)
$data = unserialize ( $foo , [ «allowed_classes» => true ]);

IntlChar

Новый класс IntlChar добавляет новую функциональность в ICU. Класс определяет несколько статических методов и констант для манипулирования символами Unicode.

Читать еще:  В приложении market произошла ошибка андроид

Результат выполнения данного примера:

Для использования это класса необходимо установить расширение Intl.

Ожидания

Ожидания являются улучшенной, обратно совместимой версией старой функции assert() . Они позволяют делать предположения с нулевой стоимостью в промышленном коде и предоставляют возможность выбрасывать пользовательские исключения в случае провала ожидания.

Вместе тем, что старое API поддерживается, assert() теперь является языковой конструкцией, принимающей первым аргументом выражения, а не только строки для оценки или логические значения для проверки.

class CustomError extends AssertionError <>

assert ( false , new CustomError ( ‘Сообщение об ошибке’ ));
?>

Результат выполнения данного примера:

Подробное описание этого функционала, а также инструкции для его конфигурирования для тестовых и промышленных сред, читайте в секции Ожидания раздела, посвященному assert() .

Групповые объявления use

Классы, функции и константы импортируемые из одного и того же namespace, теперь можно группировать в одном операторе use.

// До PHP 7
use some namespace ClassA ;
use some namespace ClassB ;
use some namespace ClassC as C ;

use function some namespace fn_a ;
use function some namespace fn_b ;
use function some namespace fn_c ;

use const some namespace ConstA ;
use const some namespace ConstB ;
use const some namespace ConstC ;

Выражение return в генераторах

Эта функциональность добавлена к генераторам, введенным в PHP 5.5. Она позволяет использовать оператор return в генераторах в качестве окончательного возвращаемого значения (возврат по ссылке недопустим). Это значение можно извлечь с помощью нового метода Generator::getReturn(), который можно использовать только после того, как генератор вернул все сгенерированные значение.

= (function() <
yield 1 ;
yield 2 ;

foreach ( $gen as $val ) <
echo $val , PHP_EOL ;
>

echo $gen -> getReturn (), PHP_EOL ;

Результат выполнения данного примера:

Возможность явно получать окончательное значение генератора является очень полезной, так как позволяет клиентскому коду, использующему генератор, получать и обработать самое последнее значение генератора, после которого точно ничего больше не будет. Это сильно проще, чем вынуждать разработчика проверять, последнее ли значение вернулось и как-то по особенному его обрабатывать.

Делегация генератора

Теперь генератор может автоматически делегировать другому генератору, объекту класса, реализующий Traversable или массиву без необходимости писать в нем дополнительную обработку полученных значений. Достигается это с помощью конструкции yield from.

function gen ()
<
yield 1 ;
yield 2 ;
yield from gen2 ();
>

function gen2 ()
<
yield 3 ;
yield 4 ;
>

foreach ( gen () as $val )
<
echo $val , PHP_EOL ;
>
?>

Результат выполнения данного примера:

Функция целочисленного деления intdiv()

Новая функция intdiv() производит целочисленное деление операндов и возвращает его результат.

Результат выполнения данного примера:

Опции сессий

Теперь session_start() принимает массив опций, которые переопределят конфигурационные директивы сессии установленные в php.ini.

Также опции были расширены включенной по умолчанию опцией session.lazy_write, которая говорит PHP о том, что файл сессии надо перезаписывать, только если изменились данные сессии, и опцией read_and_close, которую можно задать только через session_start() для того, чтобы PHP закрывал сессию сразу же как прочитает ее данные и не вносил в нее каких-либо изменений.

К примеру, для установки session.cache_limiter равным private и немедленному закрытию сессии после чтения ее данных:

preg_replace_callback_array()

Новая функция preg_replace_callback_array() позволяет писать более чистый код, когда требуется использовать функцию preg_replace_callback() . До PHP 7 при необходимости обработать разные регулярные выражения разными функциями приходилось для каждой такой обработки писать отдельный вызов функции.

Теперь можно использовать одну функцию, передавая в нее ассоциативный массив, ключами которого являются регулярные выражения, а значениями — функции обратного вызова.

Функции CSPRNG

Были добавлены две новые кроссплатформенные функции для генерации криптографически безопасных строк и целых чисел: random_bytes() и random_int() .

Теперь функция list() всегда может распаковывать объекты, реализующие ArrayAccess

Ранее функция list() не гарантировала корректную обработку объектов, реализующих ArrayAccess. Теперь это исправлено.

LornaJane Blog

In PHP 5, we already have a ternary operator, which tests a value, and then returns the second element if that returns true and the third if it doesn’t:

In PHP 7 we additionally get the ?? operator which rather than indicating extreme confusion which is how I would usually use two question marks together instead allows us to chain together a string of values. Reading from left to right, the first value which exists and is not null is the value that will be returned.

This construct is useful for giving priority to one or more values coming perhaps from user input or existing configuration, and safely falling back on a given default if that configuration is missing. It’s kind of a small feature but it’s one that I know I’ll be using as soon as my applications upgrade to PHP 7.

Related Posts

24 thoughts on “ New in PHP 7: null coalesce operator ”

Thanks for this post — I had heard about the null coalesce operator (and have had several instances this past week when I wished I had it available already) but the ternary shorthand was new to me!

Maybe you meant «reading from LEFT to RIGHT»?

«Reading from right to left» —> «Reading from left to right»

One of my favorite new features after type hinting 🙂

Could you explain this? You say «Reading from right to left, the first value which exists and is not null is the value that will be returned.», but then you have this snippet:

[code]
echo $a ?? $b ?? 7; // outputs 16
[/code]

I’d interpret your text as: start with 7. It exists, and is not null, so that value is returned. But it isn’t? Should the output be 7, or should the text be «left to right» ?

I had issues understanding it myself, but then again it makes sense.
The ?? operator returns the «left-hand» operand if it is not null.

Since the «left-hand» operand is not null 16 is returned, then after this,
we then evaluate the following

$a ?? 16
and as a result 16 is returned because the left-hand operand is null..

Shouldn’t that be ‘Reading from left to right’, instead of the other way around?

Thanks for explaining this usefull new operator. I would have probably glansed over it when reading about it in a list of new features!

I’ve used null coalesce in MySQL before, but it will be nice to have it in PHP. I didn’t know about that shorthand version of the ternary operator though, thanks for mentioning that! 🙂

Shouldn’t it be «Reading from left to right» instead of «right to left» ?

Small thing or not, this is exactly the type of highly practical improvements that I’m happy to see.

Читать еще:  Ошибка аутентификации что это

Wow, this is so useful!

Should it be reading left to right so first none null is 16 rather than right to left where the first none null would be 7 ?

You are all completely correct and apparently I don’t know my left from my right when I blog before coffee! I fixed it, thanks people 🙂

I admit as well that it can be very hard to understand at first if you don’t know this new syntax, but when you do it’s super useful and clean and it will save you a lot of keystrokes in some cases!

Thanks for sharing it

I just love the fact that the shorthand form of the ternary operator is called the Elvis Operator. Kinda cute 🙂

Great that it doesn’t seem to throw an E_NOTICE whereas the ternary does. When [code]$foo[‘bar’][/code] is undefined using [code]$foo[‘bar’] ?: »[/code] throws an E_NOTICE forcing me to write it more verbosely like [code]isset($foo[‘bar’]) ? $foo[‘bar’] : »[/code]. Now I can just use [code]$foo[‘bar’] ?? »[/code]

After uses for a while, this is just a potential bugger. Because it checks NULL and NULL value only. This is just not classic PHP. If you love what PHP does with if($var). then you know what I mean. NULL is not covering empty string. So return $a??$b??$c??$d; if $b is empty string, it will be returned without checking $c and $d any more.

We have $a?:$b?:$c?:$d already, which are checking TRUE and it is very PHP. Less is more.

Shouldn’t it be «Reading from left to right» instead of «right to left» ?

Leave a Reply Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

What’s The Difference Between ?? And ?: In PHP?

A comparison and analysis of the Null Coalescing and Evlis/Shorthand Ternary Operator in PHP

  • By Daniyal Hamid
  • January 08, 2020
  • Comments
In This Article

In this article, we’ll compare and analyze the two shorthand conditional operators in PHP, the shorthand ternary operator, i.e. the evlis operator ( ?: ), and the null coalescing operator ( ?? ).

?: (Elvis Operator)

Since PHP 5.3+, we can use the shorter ternary operator syntax by leaving out the middle part of the ternary operator for a quick shorthand evaluation:

This shorthand syntax is also referred to as the elvis operator ( ?: ). Note that the following statements are equivalent:

The statements above translate to; if expr1 evaluates to true , return expr1, otherwise return expr2.

If a falsy value is encountered, the evlis operator will return the second operand. Or, if a truthy value is encountered, the first operand (i.e. the truthy value) is returned. Note, however, that when the left hand side of the elvis operator evaluates to true , the right hand side of the expression is not evaluated. This is because of short-circuiting, which means the second operand is executed or evaluated only if the first operand does not evaluate to true .

It is important to remember that the following values are considered false in PHP:

  • Boolean false ;
  • Integer 0 ;
  • Float 0.0 ;
  • String ‘0’ or «0» ;
  • An empty string (i.e. » or «» );
  • An empty array (i.e. [] or array() );
  • null ;
  • SimpleXML objects created from empty tags.

Note that the strings «00», «0.0», «», and «false» all evaluate to boolean true which is different from string ‘0’ or boolean false .

Ternary Chaining:

The ternaries can be chained (i.e. it returns the first truthy value it encounters), for example:

This is the same as writing a series of if/elseif/else statements, for example:

Similarities With Other Languages:

In certain programming languages (such as Perl, Python, Ruby, and JavaScript), the elvis operator is written as the OR operator (typically || or or ). This has the same behavior, i.e. returning its first operand if it evaluates to true , or evaluating and returning its second operand otherwise.

?? (Null Coalescing Operator)

Introduced in PHP 7, the null coalescing operator ( ?? ) has the following syntax:

Which means that expr1 is returned when expr1 exists and is NOT null ; otherwise it returns expr2 . This is the same as the following:

For a null coalescing operator, the only thing that matters is that the variable exists and is not null so even falsy values are given a pass.

??= (Null Coalescing Assignment Operator):

Starting PHP 7.4+, we can use the null coalescing assignment operator ( ??= ) — a shorthand to assign a value to a variable if it hasn’t been set already. Consider the following examples, which are all equivalent:

Coalescing Chaining:

The coalescing can be chained (i.e. it returns the first defined value it encounters), for example:

In case there’s no defined value in the coalescing chain, a «Notice: Undefined variable: . » message is shown.

The table below shows a side-by-side comparison of the two operators against a given expression:

Expressionecho ($x ?: ‘hello’)echo ($x ?? ‘hello’)
$x = «»;‘hello’«»
$x = null;‘hello’‘hello’
$x;‘hello’
(and Notice: Undefined variable: x)
‘hello’
$x = [];‘hello’[]
$x = [‘a’, ‘b’];[‘a’, ‘b’][‘a’, ‘b’]
$x = false;‘hello’false
$x = true;truetrue
$x = 1;11
$x = 0;‘hello’
$x = -1;-1-1
$x = ‘1’;‘1’‘1’
$x = ‘0’;‘hello’‘0’
$x = ‘-1’;‘-1’‘-1’
$x = ‘random’;‘random’‘random’
$x = new stdClass;object(stdClass)object(stdClass)

Did you find the article useful? Or do you have something else to add? Please do let us know in the comments section.

You Might Also Like

Legacy

The «Legacy» audio clip is composed of a combination of various string, percussion and bass instruments which are meant to create a slow-moving dramatic ambience track.

Assign (jQuery)

Assign keyboard shortcuts to any action you wish to perform on a web page. This can particularly be useful for web applications or to enhance accessibility on web pages. It’s very easy to use as the code syntax is very similar to jQuery’s «bind» and «on» methods.

Emergence

Emergence is a short sound clip that produces a sound like pixels or pieces of an object forming or coming together. It can be used as a part of a logo ident or to highlight object movement or state transition.

Ссылка на основную публикацию
Adblock
detector