MidТеория5 min

Операторы

Арифметические, битовые, сравнение, null coalescing, spread

Операторы 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 при неявном преобразовании.


Вопросы с экзамена ZCE

Проверь себя

5 из 68

Каким будет вывод следующего кода? ```php function a($number) { return (b($number) * $number); } function b(&$number) { ++$number; } echo a(5); ```

Дан следующий код: Какие из следующих утверждений верны? ```php interface A {} class C {} class B extends C {} class E extends C implements A {} class D extends E{} $b = new B(); $e = new E(); $c = new C(); $a = new B(); $d = new D(); ```

Выберите все правильные варианты

Посмотрите на следующий код. Что нужно заменить, чтобы `$b` имело значение 2 в конце скрипта? (Возможно несколько ответов) ```php function myFunction($a) { $a++; } $b = 1; myFunction($b); ```

Какие из следующих вариантов являются допустимыми переменными PHP? (Выберите 3)

Выберите все правильные варианты

Каким будет вывод следующего кода? ```php $a = 7; $b = 4; function b($a, $b) { global $a, $b; $a += 7; $a++; $b += $a; return true; } echo $b, $a; ```

Code Challenges

Простой калькулятор

PHP

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

Test Cases

1. Input: 10, "+", 5→ Expected: 15
2. Input: 10, "-", 3→ Expected: 7
3. Input: 4, "*", 3→ Expected: 12
4. Input: 15, "/", 3→ Expected: 5