extract($array) створює змінні в поточній області видимості з ключів масиву:
extract(['name' => 'Оля', 'role' => 'admin']);
echo $name; // 'Оля'
compact('name', 'role') - зворотне: збирає змінні в масив за іменами.
Чому extract небезпечний:
- Перезапис змінних. За замовчуванням
extractперезаписує наявні змінні. Якщо масив прийшов від користувача, нападник може підмінити будь-яку змінну функції:
$isAdmin = false;
extract($_POST); // POST isAdmin=1 → $isAdmin = '1'
if ($isAdmin) { /* ... */ }
Історично це була реальна вразливість у CMS і плагінах.
- Невидимі змінні. Читач коду не бачить, звідки взялася
$role- її оголошення ніде немає. IDE й статичний аналіз теж не бачать. - Опечатки не ловляться: відсутній ключ просто не створить змінну, і код отримає «Undefined variable» далі.
Якщо extract таки потрібен: ніколи з даними від користувача і з прапорцем, що забороняє перезапис - extract($data, EXTR_SKIP).
compact безпечніший, але має свої мінуси:
return view('orders.show', compact('order', 'items', 'total'));
- Імена змінних - рядки: перейменування змінної в IDE не оновить рядок у
compact, і ключ зникне. - Відсутня змінна - лише попередження.
Явний масив читабельніший і надійніший при рефакторингу:
return view('orders.show', ['order' => $order, 'items' => $items, 'total' => $total]);
Де ці функції живуть легітимно: шаблонізатори (Blade під капотом робить extract даних подання в області видимості шаблону) - там джерело даних контрольоване, і це їхня пряма задача.