extract()
PHP extract() импортирует ключи ассоциативного массива как переменные в текущую таблицу символов. Синтаксис, флаги и примеры.
Что такое extract() в PHP?
extract() — встроенная функция PHP, которая импортирует элементы ассоциативного массива в текущую таблицу символов, превращая каждый ключ в переменную со значением соответствующего элемента массива. Она является обратной к compact(), которая строит массив из существующих переменных.
Её сигнатура:
extract(array &$array, int $flags = EXTR_OVERWRITE, string $prefix = ""): int$array— исходный массив. Переменными становятся только строковые ключи, являющиеся допустимыми именами переменных PHP. Числовые ключи пропускаются, если не используется флаг с префиксом.$flags— управляет обработкой конфликтов имён с существующими переменными (см. Флаги и поведение).$prefix— строка, добавляемая к именам переменных при использовании флага с префиксом.
Функция возвращает количество успешно импортированных переменных.
Как использовать extract() в PHP
Начните с ассоциативного массива, ключи которого — это нужные имена переменных:
$person = [
'name' => 'John Doe',
'age' => 30,
'email' => '[email protected]',
];
extract($person);
echo $name; // John Doe
echo $age; // 30
echo $email; // [email protected]После extract($person) в текущей области видимости создаются три переменные — $name, $age и $email, — каждая содержит значение соответствующего ключа.
Извлечение только некоторых ключей
По умолчанию extract() создаёт переменные для каждого ключа. Чтобы импортировать подмножество, сначала отфильтруйте массив с помощью array_intersect_key() и array_flip():
$wanted = ['name', 'email'];
$count = extract(array_intersect_key($person, array_flip($wanted)));
echo $count; // 2
echo $name; // John Doe
echo $email; // [email protected]
// $age is NOT createdarray_flip($wanted) преобразует ['name', 'email'] в ['name' => 0, 'email' => 1], а array_intersect_key() оставляет только эти ключи из $person, поэтому извлекаются лишь $name и $email.
Флаги и поведение
Второй параметр управляет тем, как обрабатываются существующие переменные при конфликте имён ключа с уже существующей переменной. Наиболее распространённые флаги:
| Флаг | Поведение |
|---|---|
EXTR_OVERWRITE | По умолчанию. Перезаписывает существующую переменную с тем же именем. |
EXTR_SKIP | Оставляет существующую переменную нетронутой и пропускает этот ключ. |
EXTR_PREFIX_SAME | При конфликте добавляет к новой переменной $prefix. |
EXTR_PREFIX_ALL | Добавляет $prefix ко всем импортируемым переменным. |
EXTR_REFS | Импортирует переменные как ссылки на элементы массива. |
Сравните EXTR_OVERWRITE (по умолчанию) с EXTR_SKIP:
$name = 'Existing Name';
$data = ['name' => 'New Name'];
extract($data); // default: overwrites
echo $name; // New Name
$name = 'Existing Name';
extract($data, EXTR_SKIP); // keep what's already set
echo $name; // Existing NameИспользуйте EXTR_PREFIX_ALL, чтобы добавить пространство имён ко всем переменным и полностью избежать конфликтов:
$data = ['name' => 'John', 'age' => 30];
extract($data, EXTR_PREFIX_ALL, 'user');
echo $user_name; // John
echo $user_age; // 30Предупреждение о безопасности
Поскольку extract() динамически создаёт переменные из ключей, передача ей недоверенных данных может привести к перезаписи существующих переменных — в том числе критически важных или суперглобальных, таких как $_GET, $_POST и $_SESSION. Классическая уязвимость — extract($_GET), которая позволяет злоумышленнику установить любую переменную в вашем скрипте через строку запроса:
$is_admin = false;
extract($_GET); // ?is_admin=1 now makes $is_admin truthy — dangerous!Никогда не вызывайте extract() непосредственно с данными запроса. Если это необходимо, передавайте EXTR_SKIP, чтобы существующие переменные не могли быть перезаписаны, или добавляйте в белый список нужные ключи с помощью array_intersect_key(), как показано выше.
Когда использовать extract()
extract() хорошо подходит для узких, контролируемых ситуаций:
- Рендеринг шаблонов — движок представлений извлекает известный массив данных в локальные переменные непосредственно перед подключением шаблона, чтобы в нём можно было писать
$titleвместо$data['title']. - Распаковка конфигурации — преобразование небольшого доверенного конфигурационного массива в именованные переменные в начале скрипта.
В большинстве случаев явное присваивание понятнее и безопаснее extract(), потому что читатель сразу видит, какие именно переменные появляются в области видимости. Используйте функцию только тогда, когда ключи надёжны и выигрыш в читаемости очевиден.
Итоги
extract() импортирует ключи ассоциативного массива как переменные в текущей области видимости и возвращает количество созданных переменных. Поведение по умолчанию EXTR_OVERWRITE делает функцию мощной, но рискованной: всегда фильтруйте входные данные или используйте EXTR_SKIP с недоверенными данными. Чтобы сделать обратное — построить массив из переменных — используйте compact().