Junior: питання на співбесіді з теми «Масиви й рядки»
Питання з реальних співбесід з відповідями: Laravel і PHP, бази даних, JavaScript і фронтенд, Git, Docker, API, безпека й архітектура. Тими самими темами, що й тести.
4 питання
Усі три обходять масив і викликають функцію для кожного елемента, але повертають різне:
array_map- новий масив тієї ж довжини, кожен елемент перетворено.array_filter- лише ті елементи, для яких функція повернулаtrue. Ключі зберігаються.array_reduce- одне значення, накопичене з усіх елементів.
$prices = [100, 250, 40];
array_map(fn (int $p): int => $p * 2, $prices); // [200, 500, 80]
array_filter($prices, fn (int $p): bool => $p > 50); // [0 => 100, 1 => 250]
array_reduce($prices, fn (int $sum, int $p): int => $sum + $p, 0); // 390
Пастки, про які питають:
- Порядок аргументів різний: у
array_mapспершу функція, уarray_filter- масив. Плутають постійно. - Після
array_filterключі «дірчасті» ([0, 2, 5]), іjson_encodeперетворить такий масив на об'єкт. Допомагаєarray_values(). array_filterбез функції прибирає всі «порожні» значення - разом із0і'0', що інколи несподівано.
Жодна з функцій не змінює початковий масив - усі повертають новий.
Рядок у PHP - це послідовність байтів, а не символів. strlen() рахує байти. У UTF-8 кожна кирилична літера займає 2 байти, тож «привіт» - 12 байтів.
strlen('привіт'); // 12
mb_strlen('привіт'); // 6
mb_substr('привіт', 0, 3); // 'при'
substr('привіт', 0, 3); // зламаний символ: 'п' і половина 'р'
Правило: для тексту, де можуть бути не лише латинські літери, використовуйте mb_*-функції: mb_strlen, mb_substr, mb_strtoupper, mb_str_split. Байтові функції зріжуть символ посередині, і в результаті з'явиться «�».
Нюанси:
mb_*рахують кодові точки Unicode. Емодзі з модифікатором шкіри чи прапор складаються з кількох точок, і для «видимих символів» потрібенgrapheme_strlen()з розширення intl.strlen()не помилка - він потрібен, коли важливі саме байти: розмір тіла запиту, обмеження колонки в байтах.- У Laravel
Str::length(),Str::limit()уже працюють черезmb_*.
Усі три перевіряють «чи є значення», але з різною семантикою:
isset($a['key'])- ключ існує і значення неnull.array_key_exists('key', $a)- ключ існує, хай навіть зі значеннямnull.empty($a['key'])- ключа немає або значення «порожнє»:null,false,0,0.0,'','0',[].
$data = ['name' => '', 'phone' => null, 'age' => 0];
isset($data['phone']); // false - значення null
array_key_exists('phone', $data); // true - ключ є
empty($data['age']); // true - 0 вважається порожнім
empty($data['name']); // true
isset($data['missing']); // false, без попередження
Де це важливо:
- PATCH-запит до API:
{"phone": null}означає «очистити телефон», а відсутній ключ - «не чіпати». Розрізнити допоможе лишеarray_key_exists(у Laravel -$request->has('phone')проти$request->filled('phone')). empty('0')-true. Рядок «0» у формі (кількість, рейтинг) стане «порожнім». Для чисел краще явні перевірки.- Вкладені ключі:
isset($a['user']['address']['city'])безпечно перевіряє весь ланцюжок без попереджень.
isset і empty - мовні конструкції, а не функції: не кидають попереджень на неіснуючих змінних і ключах. Через це їх легко використати для приховування опечаток - isset($usr) мовчки поверне false.
Для об'єктів: isset($obj->prop) для неініціалізованої типізованої властивості - false; property_exists() перевіряє, чи оголошена властивість у класі.
Основні функції:
explode(',', 'php,laravel,vue'); // ['php', 'laravel', 'vue']
explode(',', 'a,b,c,d', 2); // ['a', 'b,c,d'] - не більше 2 частин
implode(', ', ['php', 'laravel']); // 'php, laravel'
str_split('abcdef', 2); // ['ab', 'cd', 'ef'] - байтами!
mb_str_split('привіт', 2); // ['пр', 'ив', 'іт'] - символами
preg_split('/[\s,;]+/', 'php, laravel; vue', -1, PREG_SPLIT_NO_EMPTY);
// ['php', 'laravel', 'vue'] - кілька роздільників
Типові пастки:
- Порожній рядок:
explode(',', '')повертає['']- масив з одним порожнім елементом, а не порожній масив. Для введення користувача часто потрібнеarray_filter(array_map('trim', explode(',', $input))). - Пробіли:
explode(',', 'a, b')дає['a', ' b']- з пробілом. Звідсиarray_map('trim', ...). - Кирилиця:
str_splitділить байти й ламає багатобайтові символи. Для тексту -mb_str_split. - CSV не розбирають через
explode: значення можуть містити коми в лапках ("Київ, Україна"). Для цьогоstr_getcsv()чиSplFileObjectзREAD_CSV.
У Laravel зручніше через Str і колекції:
Str::of('php, laravel , vue')->explode(',')->map(fn ($s) => trim($s))->filter();