Junior: питання на співбесіді з теми «PHP 8+»
Питання з реальних співбесід з відповідями: Laravel і PHP, бази даних, JavaScript і фронтенд, Git, Docker, API, безпека й архітектура. Тими самими темами, що й тести.
3 питання
Іменовані аргументи (PHP 8.0) дозволяють передавати аргументи за іменем параметра, а не лише за позицією.
// Позиційно: що означає true? а 0?
htmlspecialchars($text, ENT_QUOTES, 'UTF-8', false);
// Іменовано
htmlspecialchars($text, double_encode: false);
str_pad(string: 'x', length: 5, pad_type: STR_PAD_LEFT);
Переваги:
- Читабельність для булевих прапорців і «магічних» чисел:
new Invoice(paid: true, sendEmail: false)замістьnew Invoice(true, false). - Пропуск необов'язкових параметрів: передати лише останній, не перелічуючи значення за замовчуванням для всіх попередніх.
- Будь-який порядок: іменовані аргументи можна передавати не в порядку оголошення.
- Разом з constructor promotion дають зручні value objects і DTO:
new Address(city: 'Київ', street: 'Хрещатик').
Правила:
- Спершу позиційні, потім іменовані:
f(1, b: 2)- так;f(a: 1, 2)- ні. - Один параметр не можна передати двічі.
- Невідоме ім'я - помилка.
- Для variadic-параметрів (
...$args) іменовані аргументи збираються в масив з рядковими ключами.
Застереження для авторів бібліотек: з іменованими аргументами назва параметра стає частиною публічного API. Перейменування $str на $string у новій версії зламає код, що викликав функцію іменовано. Тому в бібліотеках назви параметрів змінюють так само обережно, як і назви методів.
First-class callable syntax (PHP 8.1) створює замикання (Closure) з функції чи методу, записавши (...) замість аргументів.
$length = strlen(...);
$length('привіт'); // 12
$format = $this->formatPrice(...); // метод об'єкта
$create = User::create(...); // статичний метод
array_map(trim(...), $lines);
array_filter($users, $this->isActive(...));
Чим краще за старі способи передати функцію:
array_map('trim', $lines); // рядок
array_filter($users, [$this, 'isActive']); // масив
array_filter($users, fn ($u) => $this->isActive($u)); // обгортка
- Перевіряється одразу: якщо методу не існує чи він недоступний, помилка виникне в момент створення, а не десь пізніше при виклику.
- Рефакторинг і IDE: «перейти до визначення» і перейменування методу працюють - на відміну від імені в рядку
'isActive'. - Видимість:
$this->privateMethod(...)усередині класу створює замикання, яке можна передати назовні й викликати, - а[$this, 'privateMethod']поза класом не спрацює. - Статичний аналіз бачить сигнатуру й перевіряє типи.
Обмеження: не працює з nullsafe ($obj?->method(...) - помилка) і з new Foo(...).
PHP 8.5 доповнив це оператором конвеєра |>, який передає значення в callable праворуч: $text |> trim(...) |> strtoupper(...).
PHP 8.0 (листопад 2020) - один з найбільших релізів мови. Головне:
Мова:
- Іменовані аргументи -
f(limit: 10). - Constructor property promotion - властивості в параметрах конструктора.
- Union-типи -
int|string, плюс типmixedі тип поверненняstatic. match- вираз зі строгим порівнянням і без провалювання.- Nullsafe-оператор
?->. - Атрибути -
#[Route('/users')]замість анотацій у PHPDoc. throwяк вираз -$user ?? throw new NotFound().catchбез змінної -catch (TimeoutException).
Суворіша поведінка:
- Порівняння числа з рядком:
0 == 'abc'теперfalse. - Помилки замість попереджень: багато внутрішніх функцій кидають
TypeErrorчиValueErrorпри неправильних аргументах, а арифметика з нечисловим рядком -TypeError. - Узгоджені сигнатури вбудованих функцій і перевірка сумісності методів при успадкуванні.
Нові функції: str_contains(), str_starts_with(), str_ends_with(), get_debug_type(), fdiv().
Продуктивність: JIT-компілятор (для обчислювальних задач; типовому веб-застосунку дає небагато) і загальні оптимізації рушія.
Чому це важливо на співбесіді: більшість сучасного PHP-коду спирається саме на ці можливості, а суворіші правила PHP 8 - часта причина проблем при оновленні старих застосунків з PHP 7.