Operators

The operators, in order of decreasing precedence, are:
Operator precedence, from highest to lowest
clone new clone, new
[] array
++ -- ~ @
(bool) (int) (float) (string) (array) (object) ……
pre-ncrement,
pre-decrement,
error suppression
type casting
instanceof types
! logical
*  /  % arithmetic
+  -  . arithmetic and string
<<   >> bitwise
<  <=  >  >= comparison
==  !=  === !== <> comparison
& bitwise and references
^ bitwise
| bitwise
&& logical
|| logical
?: ternary
=  +=  -=  *=  /=  .=  %=  &=  |=  <<=   >>=   => assignment
and logical
xor logical
or logical
, many uses
++  -- post-increment,
post-decrement

Note the shorthand notations for assignment operators. ($a = $a % 5) is the same as ($a%=5), which is the remainder of $a divided by 5. An assignment evaluates to the value of the assignment, so ($a=$b=5) assign 5 to $a because ($b=5) evaluates to 5.

Placing ++ at the back of a variable increases its value by one after the whole statement has been executed. Placing it in front of a variable increases its value by one before the statement is executed.

The comparison operators are:
Comparison operators
== equals
=== equals in value and type
!=,<> does not equal
!== equals in neither value nor type
is strictly greater than
< is strictly less than
>= is greater than or equal to
<= is less than or equal to

Caution must be taken when comparing floats for equality, for the internal representation of floats may offset the precise value slightly.

The logical operators are: !(not), &&(and), ||(or), and, xor and or. Notice that the two variations of the logical operators and and or operate at different precedences. A xor expression evaluates to true only if one of the operands (but not both) evaluates to true. For example,
echo ($b=(”5”==5) xor $d=(“5”===5));
The resulting output is 1 because $b=(”5”==5) evaluates to true while $d=(“5”===5) evaluates to false.

For bitwise operators:
Bitwise operators
$a&$b: 1 for which both corresponding bits are 1s
$a|$b: 1 for which either corresponding bit is 1
$a^$b: 1 for which either but not both bit is 1
~$a: inverts the bits
$a >> 3: shifts the binary form 3 bits to the right
$a << 2: shifts the binary form 2 bits to the left

To cast a type out of an expression, include the bracketed type in front of the expression:
echo ((int)4.7+1);     # 5
echo ((bool)5.7);       # 1
The casts available are:
Type cast operators
(int), (integer) -- integer
(bool), (boolean) -- boolean
(float), (double), (real) -- float
(string) -- string
(array) -- array
(object) -- object
(unset) -- null
If ‘display_errors’ is set to ‘on’ in php.ini, error and warning messages will be displayed. These messages can be suppressed with the @ operator.

<!DOCTYPE html>
<html><body>
<?php
ini_set("display_errors","on");
echo @(10/0);
$my_file = @file ('non_existent_file') or
                 die ("Failed opening file");
?>
</body></html>
Since PHP 5.6, the ** (exponentiation) operator raises the left operand to the power of the right operand, and **= is its combined assignment form. ** is right-associative, so a chain like 2 ** 3 ** 2 evaluates as 2 ** (3 ** 2), not (2 ** 3) ** 2:

<?php
printf("2 ** 3 ==  %d\n", 2 ** 3);
printf("2 ** 3 ** 2 == %d\n", 2 ** 3 ** 2);

$a = 2;
$a **= 3;
printf("a == %d\n", $a);
?>

2 ** 3 == 8 2 ** 3 ** 2 == 512 a == 8
Since PHP 7.0, the <=> (spaceship) operator performs a three-way comparison between two values. It returns an integer that is negative, zero, or positive depending on whether the left-hand operand is respectively less than, equal to, or greater than the right-hand operand – using the same rules as <, == and >. It works on numbers, strings, and arrays (compared element by element).
Used directly, returns -1, 0, or 1:
<?php
var_dump(1 <=> 2);
var_dump(2 <=> 2);
var_dump(3 <=> 2);
var_dump("a" <=> "b");
var_dump([1, 2, 3] <=> [1, 2, 3]);
?>

int(-1) int(0) int(1) int(-1) int(0)
The spaceship operator's most common use is inside a usort() (or similar) callback, since it produces exactly the -1/0/1 result that these functions expect – replacing longer if/elseif chains or subtraction tricks that only work for numbers:

<?php
$numbers = [5, 3, 8, 1, 9, 2];

usort($numbers, function ($a, $b) {
  return $a <=> $b;
});

echo implode(", ", $numbers) . "\n";

$people = [
  ["name" => "Charlie", "age" => 35],
  ["name" => "Alice", "age" => 28],
  ["name" => "Bob", "age" => 42],
];

usort($people, fn($a, $b) => $a["age"] <=> $b["age"]);

foreach ($people as $person) {
  echo $person["name"] . " (" . $person["age"] . ")\n";
}
?>

1, 2, 3, 5, 8, 9 Alice (28) Charlie (35) Bob (42)
PHP has three operators for gracefully handling null. The null coalescing operator ?? (PHP 7.0) returns its left operand if that value is set and not null, otherwise it returns the right operand – without raising a warning for an undefined variable or array key.

<?php
$data = ["name" => "Alice"];

// ?? returns the left side if it is set and not null, else the right side.
echo ($data["name"] ?? "Anonymous") . "\n";
echo ($data["email"] ?? "no-email@example.com") . "\n";

// Works with undefined array keys/variables without a warning, unlike isset() + ternary.
echo ($undefinedVar ?? "fallback") . "\n";

// Chainable: evaluated left to right, stopping at the first set, non-null value.
$config = [];
echo ($config["timeout"] ?? $data["timeout"] ?? 30) . "\n";
?>

Alice no-email@example.com fallback 30
PHP 7.4 added the shorthand assignment ??=: $a ??= $b assigns $b to $a only when $a is currently null or unset, leaving any existing non-null value untouched.

<?php
$options = ["color" => "red"];

// ??= assigns only if the key/variable is null or not set.
$options["color"] ??= "blue";
$options["size"] ??= "medium";

echo $options["color"] . "\n";
echo $options["size"] . "\n";

print_r($options);
?>

red medium Array ( [color] => red [size] => medium )
PHP 8.0's nullsafe operator ?-> applies the same short-circuiting idea to an entire chain of property accesses or method calls: $user?->address?->city evaluates to null the instant any link in the chain is null, instead of throwing an error for accessing a property or calling a method on null.

<?php
class Address {
  public string $city = "Paris";
}
class User {
  public ?Address $address = null;
}

$userWithAddress = new User();
$userWithAddress->address = new Address();

$userWithoutAddress = new User();

// The whole chain short-circuits to null if any link is null.
echo ($userWithAddress?->address?->city ?? "Unknown") . "\n";
echo ($userWithoutAddress?->address?->city ?? "Unknown") . "\n";

var_dump($userWithoutAddress?->address?->city);
?>

Paris Unknown NULL
PHP 8.5 introduces the pipe operator |>: $value |> $callable calls $callable with $value as its only argument, equivalent to $callable($value) but written in the order the data actually flows – left to right – instead of nesting calls inside out.
Chaining pipes reads as a left-to-right pipeline instead of nested function calls like strrev(strtoupper($str)).
<?php
// The left-hand expression becomes the sole argument to the right-hand callable.
$result = "Hello World" |> strlen(...);
var_dump($result);

// Chaining runs left to right: strtoupper() first, then strrev() on its result.
$shout = "hello world"
  |> strtoupper(...)
  |> strrev(...);
echo $shout . "\n";
?>

int(11) DLROW OLLEH
The right-hand side must be an expression that evaluates to a callable – usually function(...) first-class callable syntax, as below with a user-defined function. A bare function name with no parentheses does not work here, since PHP would try to resolve it as a constant rather than a function reference.

<?php
declare(strict_types=1);

function double(int $n): int {
  return $n * 2;
}

// Works with any callable, not just built-in functions.
$value = 5 |> double(...) |> double(...);
echo $value . "\n";
?>

20