Операторы PHP
Арифметические операторы
<?php
declare(strict_types=1);
$a = 10;
$b = 3;
echo $a + $b; // 13 Addition
echo $a - $b; // 7 Subtraction
echo $a * $b; // 30 Multiplication
echo $a / $b; // 3.33 Division (returns float!)
echo $a % $b; // 1 Modulo
echo $a ** $b; // 1000 Exponentiation (PHP 5.6+)
// Integer division
echo intdiv(10, 3); // 3 (no remainder)
Ловушка экзамена: Оператор
/ВСЕГДА возвращаетfloat, если результат не является целым числом. Даже10 / 2возвращаетint, но10 / 3возвращаетfloat. Для гарантированного целочисленного деления используйтеintdiv().
<?php
declare(strict_types=1);
// Division by zero behavior
// echo 10 / 0; // DivisionByZeroError (PHP 8.0+)
// echo 10 % 0; // DivisionByZeroError (PHP 8.0+)
echo intdiv(10, 0); // DivisionByZeroError
Операторы присваивания
<?php
declare(strict_types=1);
$a = 10;
$a += 5; // $a = $a + 5; => 15
$a -= 3; // $a = $a - 3; => 12
$a *= 2; // $a = $a * 2; => 24
$a /= 4; // $a = $a / 4; => 6.0
$a %= 5; // $a = $a % 5; => 1
$a **= 3; // $a = $a ** 3; => 1
$a .= ' px'; // $a = $a . ' px' => "1 px"
// Null coalescing assignment (PHP 7.4+)
$b ??= 'default'; // If $b is null, assign 'default'
Операторы сравнения
Нестрогое (==) vs строгое (===) сравнение
<?php
declare(strict_types=1);
// == (loose comparison) — compares values with type juggling
var_dump(0 == 'foo'); // bool(false) — Changed in PHP 8.0!
var_dump(0 == ''); // bool(false) — Changed in PHP 8.0!
var_dump('' == null); // bool(true)
var_dump(0 == null); // bool(true)
var_dump('' == false); // bool(true)
var_dump(0 == false); // bool(true)
var_dump(1 == '1'); // bool(true)
var_dump(1 == '1.0'); // bool(true)
var_dump(100 == '1e2'); // bool(true) — scientific notation!
var_dump('0' == false); // bool(true)
var_dump('0' == null); // bool(false)
// === (strict comparison) — compares value AND type
var_dump(0 === false); // bool(false)
var_dump(0 === null); // bool(false)
var_dump(1 === '1'); // bool(false)
var_dump(1 === 1); // bool(true)
Ловушка экзамена: В PHP 8.0 кардинально изменилось сравнение
0 == 'string'. До PHP 8.0 это былоtrue(строка приводилась к 0). Начиная с PHP 8.0 —false(число приводится к строке). Но0 == ''тоже сталоfalseв PHP 8.0!
Таблица нестрогого сравнения (PHP 8.0+)
true |
false |
1 |
0 |
-1 |
"1" |
"0" |
"" |
null |
[] |
|
|---|---|---|---|---|---|---|---|---|---|---|
true |
T | F | T | F | T | T | F | F | F | F |
false |
F | T | F | T | F | F | T | T | T | T |
null |
F | T | F | T | F | F | F | T | T | T |
0 |
F | T | F | T | F | F | T | F | T | F |
Оператор Spaceship <=>
<?php
declare(strict_types=1);
// Returns -1, 0, or 1
echo 1 <=> 2; // -1 (left is less)
echo 2 <=> 2; // 0 (equal)
echo 3 <=> 2; // 1 (left is greater)
// Useful for sorting
$people = ['Charlie', 'Alice', 'Bob'];
usort($people, fn(string $a, string $b): int => $a <=> $b);
// Result: ['Alice', 'Bob', 'Charlie']
// Multi-level sorting
$users = [
['name' => 'Bob', 'age' => 30],
['name' => 'Alice', 'age' => 25],
['name' => 'Alice', 'age' => 30],
];
usort($users, function (array $a, array $b): int {
return $a['name'] <=> $b['name']
?: $a['age'] <=> $b['age'];
});
Null Coalescing оператор (??)
<?php
declare(strict_types=1);
// ?? returns the left operand if it's not null
$username = $_GET['user'] ?? 'anonymous';
// Chaining
$value = $a ?? $b ?? $c ?? 'default';
// Equivalent to:
$value = isset($a) ? $a : (isset($b) ? $b : (isset($c) ? $c : 'default'));
// Important: ?? checks for null, NOT for falsy values
$zero = 0;
$empty = '';
$false = false;
echo $zero ?? 'default'; // 0 (not null!)
echo $empty ?? 'default'; // '' (not null!)
echo $false ?? 'default'; // false (not null!)
$null = null;
echo $null ?? 'default'; // 'default' (is null)
Ловушка экзамена:
??проверяет ТОЛЬКО наnull(аналогisset()). Значения0,'',false,[]— это НЕnull, и??вернёт их, а не значение по умолчанию. Не путайте с тернарным оператором?:.
Разница между ?? и ?:
<?php
declare(strict_types=1);
$zero = 0;
$empty = '';
echo $zero ?? 'default'; // 0 (?? checks null only)
echo $zero ?: 'default'; // default (?: checks falsy)
echo $empty ?? 'default'; // '' (?? checks null only)
echo $empty ?: 'default'; // default (?: checks falsy)
// ?? does NOT trigger "undefined variable" warning
echo $undefined ?? 'safe'; // 'safe' (no warning)
// echo $undefined ?: 'oops'; // Warning: Undefined variable (PHP 8.0+)
Логические операторы
<?php
declare(strict_types=1);
// && and AND — logical AND (different precedence!)
// || and OR — logical OR (different precedence!)
$a = true;
$b = false;
// && has HIGHER precedence than =
$c = $a && $b; // $c = (true && false) => false
// AND has LOWER precedence than =
$d = $a and $b; // ($d = true) and false => $d is TRUE!
var_dump($c); // bool(false)
var_dump($d); // bool(true) — SURPRISE!
Ловушка экзамена:
&&иand— это РАЗНЫЕ операторы с разным приоритетом!&&выполняется ДО присваивания, аand— ПОСЛЕ. Аналогично||иor. Всегда используйте&&и||.
Short-circuit evaluation
<?php
declare(strict_types=1);
function expensive(): bool
{
echo 'Called! ';
return true;
}
// If left side of && is false, right side is NOT evaluated
false && expensive(); // Nothing printed
// If left side of || is true, right side is NOT evaluated
true || expensive(); // Nothing printed
// This is commonly used for guard clauses
$user = null;
$name = $user && $user->getName(); // Safe, no error
Битовые операторы
<?php
declare(strict_types=1);
$a = 0b1010; // 10 in decimal
$b = 0b1100; // 12 in decimal
echo $a & $b; // 8 (AND: 1000)
echo $a | $b; // 14 (OR: 1110)
echo $a ^ $b; // 6 (XOR: 0110)
echo ~$a; // -11 (NOT)
echo $a << 1; // 20 (shift left: 10100)
echo $a >> 1; // 5 (shift right: 0101)
// Practical example: permission flags
const PERM_READ = 0b001; // 1
const PERM_WRITE = 0b010; // 2
const PERM_EXECUTE = 0b100; // 4
$userPerms = PERM_READ | PERM_WRITE; // 3 (0b011)
// Check permission
if ($userPerms & PERM_READ) {
echo 'Can read';
}
if (!($userPerms & PERM_EXECUTE)) {
echo 'Cannot execute';
}
Spread оператор (...)
<?php
declare(strict_types=1);
// Unpacking function arguments
function sum(int ...$numbers): int
{
return array_sum($numbers);
}
echo sum(1, 2, 3, 4, 5); // 15
$nums = [1, 2, 3];
echo sum(...$nums); // 6
// Array unpacking (PHP 7.4+)
$first = [1, 2, 3];
$second = [4, 5, 6];
$merged = [...$first, ...$second]; // [1, 2, 3, 4, 5, 6]
// Named argument unpacking (PHP 8.0+)
function createUser(string $name, int $age, string $email): array
{
return compact('name', 'age', 'email');
}
$args = ['name' => 'Alice', 'age' => 25, 'email' => '[email protected]'];
$user = createUser(...$args);
// String-keyed array unpacking (PHP 8.1+)
$defaults = ['color' => 'red', 'size' => 'M'];
$custom = ['size' => 'L'];
$config = [...$defaults, ...$custom];
// ['color' => 'red', 'size' => 'L'] — later values override
Ловушка экзамена: Spread оператор для массивов со строковыми ключами доступен только с PHP 8.1+. До этого работал только с числовыми ключами. На экзамене могут дать код с
[...$assocArray]и спросить версию PHP.
Оператор подавления ошибок (@)
<?php
declare(strict_types=1);
// @ suppresses error messages (BAD PRACTICE!)
$value = @file_get_contents('nonexistent.txt'); // No warning
// In PHP 8.0+, @ no longer suppresses fatal errors
// @$result = 1 / 0; // Still throws DivisionByZeroError
// NEVER use @ in production code
// Instead, handle errors properly:
$value = file_get_contents('nonexistent.txt');
if ($value === false) {
// Handle error
}
Приоритет операторов
Порядок от ВЫСШЕГО к НИЗШЕМУ приоритету:
| Приоритет | Оператор | Описание |
|---|---|---|
| Высший | clone, new |
Создание объектов |
** |
Возведение в степень | |
++, --, ~, (int), (float) и т.д. |
Инкремент, приведение типов | |
instanceof |
Проверка типа | |
! |
Логическое НЕ | |
*, /, % |
Умножение/деление | |
+, -, . |
Сложение/конкатенация | |
<<, >> |
Побитовый сдвиг | |
<, <=, >, >= |
Сравнение | |
==, !=, ===, !==, <=> |
Равенство | |
& |
Побитовое И | |
^ |
Побитовое исключающее ИЛИ | |
| |
Побитовое ИЛИ | |
&& |
Логическое И | |
|| |
Логическое ИЛИ | |
?? |
Null coalescing | |
? : |
Тернарный | |
=, +=, -= и т.д. |
Присваивание | |
yield, yield from |
Генераторы | |
and |
Логическое И (низкий) | |
xor |
Логическое искл. ИЛИ | |
| Низший | or |
Логическое ИЛИ (низкий) |
Инкремент и декремент
<?php
declare(strict_types=1);
$a = 5;
echo $a++; // 5 (returns, THEN increments)
echo $a; // 6
echo ++$a; // 7 (increments, THEN returns)
// String increment (legacy behavior)
$letter = 'A';
$letter++; // 'B'
$str = 'z';
$str++; // 'aa'
$str = 'Az';
$str++; // 'Ba'
// Decrement does NOT work on strings
$letter = 'B';
$letter--; // 'B' — no effect!
Ловушка экзамена: Декремент (
--) НЕ работает на строках!$x = 'B'; $x--;— значение$xостанется'B'. А инкремент работает:$x = 'Z'; $x++;даёт'AA'.
Приведение типов
<?php
declare(strict_types=1);
// Explicit casting
$int = (int) '42abc'; // 42
$float = (float) '3.14'; // 3.14
$string = (string) 42; // '42'
$bool = (bool) 'hello'; // true
$array = (array) 'hello'; // ['hello']
$object = (object) ['a' => 1]; // stdClass with property $a = 1
// settype() modifies variable in place
$var = '42';
settype($var, 'integer');
echo $var; // 42 (now int)
Запомни: Приведение строки к
int: PHP берёт числовую часть с начала строки.(int)'42abc'= 42,(int)'abc42'= 0,(int)''= 0. В PHP 8.0+ нечисловые строки генерируютE_WARNINGпри неявном преобразовании.