Перейти к содержимому
Поиск
Php Разработка

PHP: полный мануал с примерами, функциями и ООП

Практический мануал PHP: от переменных и читаемого кода до безопасных форм, интеграций, базы данных и ООП на примере магазина. Учебный маршрут, поиск функций, подробные примеры, разбор ошибок и исходники для скачивания.

Александр НекрасовИзменено:
Практический мануал PHP: от переменных и функций к объектной модели интернет-магазина
PHP 8.5.11149 глав4458 карточек справочника
Дерево руководства

Глава 87 · Практика

Fileinfo: типы файлов, кодировки и все функции

Определение типа по содержимому: полный API finfo, все флаги, различия версий и применение при приёме документов.

Файл назван photo.jpg — есть ли внутри фотография?

Наглядная модель

Имя photo.jpg ещё не означает фотографию

В собственном учебном файле photo.jpg записан текст Hello world. Проверим, что определит сервер по содержимому.

  1. Имя: photo.jpg

    Имя — строка. Суффикс не изменяет байты файла.

  2. finfo::file

    FILEINFO_MIME_TYPE включает поиск предполагаемого формата по правилам libmagic.

  3. text/plain

    По содержимому найден обычный текст.

  4. Проверка политики

    Форма фотографии отвергнет тип. Совпадение допустимого типа потребовало бы дальнейшей проверки формата.

Fileinfo классифицирует содержимое эвристически. Права, размер, целостность формата и правила хранения остаются отдельными проверками.

К заявке приложили photo.jpg. В нашем архиве этот файл содержит обычный текст «Pickup order 104». Имя обещает фотографию, но не меняет байты. Fileinfo анализирует признаки содержимого и возвращает MIME-тип — имя предполагаемого формата, например image/jpeg или text/plain. Получим видимое решение: этот файл нельзя отправить в обработчик фотографий.

От обещания имени к решению
  1. photo.jpg содержит текст Pickup order 104
  2. new finfo(FILEINFO_MIME_TYPE) выбирает ответ в виде MIME
  3. finfo_file читает признаки содержимого
  4. text/plain → попросить настоящее изображение
ЗаписьЧто она делает
new finfo(FILEINFO_MIME_TYPE)Создать объект определителя. Константа выбирает короткое MIME-имя вместо свободного описания.
finfo_file($detector, $path)Передать определитель и путь. Возвращается строка предполагаемого типа либо false при отказе.
$type === 'image/jpeg'Сравнить точное значение; расширение имени в этом сравнении не участвует.
Текст с расширением JPG остаётся текстомСамостоятельный пример
<?php
declare(strict_types=1);

$path = __DIR__ . '/photo.jpg';
$detector = new finfo(FILEINFO_MIME_TYPE);
$type = finfo_file($detector, $path);
if ($type === false) { throw new RuntimeException('Не определить тип'); }
echo 'Содержимое: ', file_get_contents($path);
echo 'Определённый тип: ', $type, "\n";
echo $type === 'image/jpeg' ? "Продолжить проверку JPEG.\n" : "Нужно настоящее изображение JPEG.\n";
Ожидаемый результат
Содержимое: Pickup order 104
Определённый тип: text/plain
Нужно настоящее изображение JPEG.

Это локальный документ из архива, не настоящая HTTP-загрузка. Fileinfo использует базу libmagic и эвристики: даже совпавший image/jpeg ещё потребует подходящего декодера, лимитов размеров и правил доступа. Имя photo.jpg и Content-Type от отправителя не доказывают формат.

Что уже естьЧто передавать
Файл на дискеПуть в finfo_file или метод file: не требуется собирать весь файл в строку PHP.
Небольшая строка с самими байтамиСтроку в finfo_buffer или метод buffer. Строка пути здесь будет прочитана как обычные буквы.
Много файловСоздать один finfo перед циклом и использовать для каждого файла.
Один файл без специальных настроекmime_content_type даёт короткий вызов.

База magic содержит правила узнавания байтов и структуры, а не разрешения пользователей. Полный приём загрузки; Строки и байты; Объект и метод.

Установка, база сигнатур и переход от ресурса к объекту

Fileinfo по умолчанию входит в PHP; в Windows включают поставляемую php_fileinfo.dll через extension=fileinfo в используемом php.ini. Проверяйте отдельно CLI и веб-SAPI: их конфигурации могут различаться. libmagic входит в PHP с собственными исправлениями, поэтому результат и поддерживаемые форматы зависят от версии среды и базы.

Среда должна совпадать с приложением
  1. Проверили реальный SAPI и php.ini
  2. Расширение fileinfo загружено
  3. MAGIC не переопределяет базу неожиданно
  4. Собственные типовые файлы проверены на этой версии
Проверить расширение и современный тип результатаСамостоятельный пример
<?php
declare(strict_types=1);

var_dump(extension_loaded('fileinfo'));
$detector = finfo_open(FILEINFO_MIME_TYPE);
if ($detector === false) { throw new RuntimeException('Cannot initialize detector'); }
echo get_debug_type($detector), "\n";
Ожидаемый результат
bool(true)
finfo

В PHP 8.1+ возвращается объект; is_resource больше не является проверкой успешного finfo_open. На PHP 8.0 возвращался ресурс, это подтверждено исходником тега 8.0.30.

Обычно используйте встроенную базу и не задавайте MAGIC. Собственную базу выбирают для специального формата и тестируют на своём наборе файлов; она не должна загружаться из произвольного пути посетителя. finfo_open и finfo::__construct объясняют отличие false от исключения.

Все флаги Fileinfo и длительность настройки

Флаг — именованное число, выбирающее режим libmagic. Совместимые режимы объединяются побитовым |. Флаги конструктора и set_flags сохраняются у объекта, ненулевые флаги file/buffer применяются только к одному вызову. FILEINFO_NONE в таком отдельном вызове не обнуляет прежнюю настройку.

Настройка и временная замена
  1. Объект создан с MIME_TYPE
  2. Один buffer вызван с MIME_ENCODING → us-ascii
  3. Следующий buffer без флага → text/plain
  4. set_flags(MIME_ENCODING) изменит все последующие вызовы
КонстантаЧто меняется и где предел
FILEINFO_NONEБез дополнительных режимов: описательное определение. В аргументе отдельного file/buffer значение 0 сохраняет настройки объекта; чтобы сбросить их, нужен set_flags(FILEINFO_NONE).
FILEINFO_SYMLINKРежим libmagic для следования символическим ссылкам. Открытие пути также зависит от обёртки PHP/системы; отсутствие этого флага не является запретом перехода по ссылке или защитой пути.
FILEINFO_MIME_TYPEВернуть MIME-тип, например text/plain. Это удобно для точного списка допустимых типов.
FILEINFO_MIME_ENCODINGВернуть предполагаемую кодировку, например us-ascii/utf-8/binary. Это эвристика, не строгая проверка всего формата.
FILEINFO_MIMEMIME-тип и charset вместе: text/plain; charset=utf-8. Комбинация MIME_TYPE | MIME_ENCODING.
FILEINFO_COMPRESSИсторический режим анализа распакованного содержимого. В PHP отключён из-за проблем потокобезопасности; не обещайте автоматическую проверку всех вложенных архивов.
FILEINFO_DEVICESРазрешает libmagic исследовать содержимое специальных блочных/символьных устройств. Для пользовательской загрузки обычного файла такой режим не нужен.
FILEINFO_CONTINUEПродолжать поиск и возвращать все совпадения вместо первого. Результат может быть составной строкой; для проверки одного MIME-типа такой формат неудобен.
FILEINFO_PRESERVE_ATIMEПо возможности сохранить исходное время доступа. Возможность зависит от платформы и прав; это не обещание отсутствия любого изменения метаданных.
FILEINFO_RAWНе заменять непечатаемые символы описания октальными escape-последовательностями. При выводе в HTML всё равно требуется HTML-экранирование.
FILEINFO_EXTENSIONPHP 7.2+: предполагаемые расширения для найденного типа, иногда несколько через /, например jpeg/jpg/jpe/jfif. Если база не знает — ???. Это не имя загруженного файла и не безопасная политика его переименования.
FILEINFO_APPLEКоды Apple creator/type, если известны базе. Специальные метаданные, не обычный MIME-тип.
Увидеть комбинацию типа и кодировкиСамостоятельный пример
<?php
declare(strict_types=1);

var_dump(FILEINFO_MIME === (FILEINFO_MIME_TYPE | FILEINFO_MIME_ENCODING));
$detector = new finfo(FILEINFO_MIME);
echo $detector->buffer("Привет\n"), "\n";
Ожидаемый результат
bool(true)
text/plain; charset=utf-8

Этот ответ содержит параметры после точки с запятой. Если проверяете список форматов, заранее выберите MIME_TYPE, а не пытайтесь сравнить всю строку с text/plain.

Применение: принять файл, не доверяя имени и заголовку

Для загрузки сначала проверяют HTTP-метод, структуру $_FILES, код UPLOAD_ERR_*, доступ пользователя и лимит размера. Fileinfo получает серверный tmp_name после этих проверок. Предполагаемый MIME сравнивают с точным разрешённым набором. Затем выполняют подходящую проверку самого формата, назначают серверное имя и хранят файл с нужными ограничениями доступа и исполнения.

Несколько самостоятельных проверок
  1. Форма → $_FILES и код результата загрузки
  2. Размер/права/CSRF проверены
  3. Fileinfo → предполагаемый формат
  4. Проверка формата и безопасное хранение по правилам сервиса
Отвергнуть текст, переименованный в фотографиюСамостоятельный пример
<?php
declare(strict_types=1);

$detector = new finfo(FILEINFO_MIME_TYPE);
$type = $detector->file('photo.jpg');
if ($type === false) { throw new RuntimeException('Cannot detect type'); }
$allowed = ['image/jpeg', 'image/png'];
echo in_array($type, $allowed, true) ? 'continue format validation' : 'reject type';
echo "\n";
Ожидаемый результат
reject type

Это изолированная часть политики с собственным файлом, не проверка настоящей HTTP-загрузки. Успешное совпадение означало бы продолжение проверки формата, а не безусловное сохранение.

Не принимайте любой image/*: разные форматы имеют разные возможности. Даже распознанный тип не доказывает целостность или отсутствие опасных данных. Для изображения нужен подходящий декодер с ограничениями размера/ресурсов; архив и PDF требуют своих правил. Не открывайте загруженный файл через include. Полный обработчик с HTML-формой, кодами ошибок и хранением разобран в главе загрузок.

Производительность: ограничивайте размер до обработки, повторно используйте определитель в цикле, анализируйте файл через file вместо загрузки всего содержимого в дополнительную строку, если строка не нужна дальше. Это снижает лишнюю работу приложения, но не гарантирует фиксированное время/память libmagic для любого формата. Тестируйте свой набор файлов на своей версии.

Упражнение: сервис принимает только text/plain. Есть два собственных документа с разными именами, оба содержат текст. Проверьте содержимое каждого одним объектом и покажите решение без доверия к расширению.

Решение упражнения
Одинаковая политика для разных имёнСамостоятельный пример
<?php
declare(strict_types=1);

$detector = new finfo(FILEINFO_MIME_TYPE);
foreach (['note.txt', 'note.jpg'] as $path) {
    $mime = $detector->file($path);
    if ($mime === false) { throw new RuntimeException('Cannot detect type'); }
    echo $path, ': ', $mime === 'text/plain' ? 'text candidate' : 'reject', "\n";
}
Ожидаемый результат
note.txt: text candidate
note.jpg: text candidate

Оба кандидата содержат текст. Реальная политика сервиса может дополнительно проверять имя/расширение, допустимую кодировку, структуру текста и размер. Fileinfo решает только свою часть.

Функции и методы этой темы

Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.

finfo_openПодготовить определитель типов с выбранными настройками и базой сигнатур.

PHP 5.3+ / PECL fileinfo 0.1+ · fileinfo

finfo_open(int $flags = FILEINFO_NONE, ?string $magic_database = null): finfo|false

Подготовить определитель типов с выбранными настройками и базой сигнатур.

Часть вызоваДоговор
flagsОдин флаг или комбинация через |. По умолчанию FILEINFO_NONE: текстовое описание; MIME_TYPE удобнее для сравнения типов. Все флаги.
magic_databaseПуть к собственной базе сигнатур. null/пустая строка означают стандартный выбор: MAGIC environment, если задана, иначе база PHP. Обычно оставляют базу PHP и MAGIC незаданной. Nullable с 8.0.3.
РезультатВ PHP 8.1+ finfo, при неуспехе false с предупреждениями. До 8.1 функция возвращала ресурс.
Срок жизниОдин объект можно использовать для многих файлов. Он освобождается автоматически; finfo_close не нужен в современном коде.

В коде $ начинает имя переменной, = сохраняет возвращённое значение, скобки передают аргументы вызова. new finfo(...) создаёт настроенный объект; ->file(...) или ->buffer(...) вызывает его метод. === false проверяет именно неуспех, не любую пустую строку. throw new RuntimeException(...) останавливает обычный путь выполнения с объектом ошибки; catch перехватывает указанный тип, а finally завершает обязательную очистку даже при ошибке. Разбор try, catch и finally.

Один настроенный определитель
  1. PHP загрузил базу правил
  2. MIME_TYPE выбирает формат ответа
  3. Объект finfo готов к file/buffer
  4. Следующий файл проверяется тем же объектом

База magic содержит правила узнавания байтов и структуры. Это не файл с разрешениями пользователей. new создаёт объект, скобки передают настройки; ->buffer передаёт сам текст для анализа.

Подготовить определитель и узнать формат памяткиСамостоятельный пример
<?php
declare(strict_types=1);

$detector = finfo_open(FILEINFO_MIME_TYPE);
if ($detector === false) { throw new RuntimeException('Не подготовить определитель'); }
$text = "Pickup order 104\n";
echo 'Памятка: ', $text;
echo 'Формат: ', $detector->buffer($text), "\n";
Ожидаемый результат
Памятка: Pickup order 104
Формат: text/plain

Объект хранит базу правил и выбранный формат ответа. finfo_open может вернуть false; new finfo при ошибке конструктора бросает исключение, поэтому сравнение созданного объекта с false не нужно.

Одним определителем подготовить опись разных документовСамостоятельный пример
<?php
declare(strict_types=1);

$detector = finfo_open(FILEINFO_MIME_TYPE);
if ($detector === false) { throw new RuntimeException('Не подготовить определитель'); }
foreach (['pickup.txt', 'instructions.html'] as $name) {
    $type = $detector->file(__DIR__ . '/' . $name);
    if ($type === false) { throw new RuntimeException('Не определить тип'); }
    echo $name, ': ', $type, "\n";
}
Ожидаемый результат
pickup.txt: text/plain
instructions.html: text/html

Определитель создаётся до цикла и используется повторно. Каждый вызов всё равно анализирует содержимое. Текстовая памятка и HTML-инструкция требуют разных способов показа: HTML нельзя безусловно вставлять как доверенную разметку.

Отличить отказ базы типов от неправильного документаСамостоятельный пример
<?php
declare(strict_types=1);

$warned = false;
set_error_handler(static function (int $level) use (&$warned): bool {
    if ($level !== E_WARNING) { return false; }
    $warned = true;
    return true;
});
try { $detector = finfo_open(FILEINFO_MIME_TYPE, __DIR__ . '/missing.magic'); }
finally { restore_error_handler(); }
if ($detector === false) { echo "Проверка документов недоступна: база типов не загружена.\n"; }
if ($warned) { echo "Файловое предупреждение получено; нужна проверка настройки сервера.\n"; }
Ожидаемый результат
Проверка документов недоступна: база типов не загружена.
Файловое предупреждение получено; нужна проверка настройки сервера.

Отсутствует именно настроенная база, а не пользовательский документ. Не подменяйте отказ сервиса ответом «разрешённый формат». Handler показан только для контролируемого опыта и сразу восстановлен.

Сравните: finfo, finfo::file, finfo::buffer, finfo_set_flags, finfo_close. Тип, кодировка и границы определения.

finfo::__constructПодготовить определитель типов с выбранными настройками и базой сигнатур.

PHP 5.3+ / PECL fileinfo 0.1+ · fileinfo

public function __construct(int $flags = FILEINFO_NONE, ?string $magic_database = null)

Подготовить определитель типов с выбранными настройками и базой сигнатур.

Часть вызоваДоговор
flagsОдин флаг или комбинация через |. По умолчанию FILEINFO_NONE: текстовое описание; MIME_TYPE удобнее для сравнения типов. Все флаги.
magic_databaseПуть к собственной базе сигнатур. null/пустая строка означают стандартный выбор: MAGIC environment, если задана, иначе база PHP. Обычно оставляют базу PHP и MAGIC незаданной. Nullable с 8.0.3.
Результатnew создаёт finfo; при ошибке загрузки базы конструктор бросает Exception.
Срок жизниОдин объект можно использовать для многих файлов. Он освобождается автоматически; finfo_close не нужен в современном коде.

В коде $ начинает имя переменной, = сохраняет возвращённое значение, скобки передают аргументы вызова. new finfo(...) создаёт настроенный объект; ->file(...) или ->buffer(...) вызывает его метод. === false проверяет именно неуспех, не любую пустую строку. throw new RuntimeException(...) останавливает обычный путь выполнения с объектом ошибки; catch перехватывает указанный тип, а finally завершает обязательную очистку даже при ошибке. Разбор try, catch и finally.

Один настроенный определитель
  1. PHP загрузил базу правил
  2. MIME_TYPE выбирает формат ответа
  3. Объект finfo готов к file/buffer
  4. Следующий файл проверяется тем же объектом

База magic содержит правила узнавания байтов и структуры. Это не файл с разрешениями пользователей. new создаёт объект, скобки передают настройки; ->buffer передаёт сам текст для анализа.

Подготовить определитель и узнать формат памяткиСамостоятельный пример
<?php
declare(strict_types=1);

$detector = new finfo(FILEINFO_MIME_TYPE);
$text = "Pickup order 104\n";
echo 'Памятка: ', $text;
echo 'Формат: ', $detector->buffer($text), "\n";
Ожидаемый результат
Памятка: Pickup order 104
Формат: text/plain

Объект хранит базу правил и выбранный формат ответа. finfo_open может вернуть false; new finfo при ошибке конструктора бросает исключение, поэтому сравнение созданного объекта с false не нужно.

Одним определителем подготовить опись разных документовСамостоятельный пример
<?php
declare(strict_types=1);

$detector = new finfo(FILEINFO_MIME_TYPE);
foreach (['pickup.txt', 'instructions.html'] as $name) {
    $type = $detector->file(__DIR__ . '/' . $name);
    if ($type === false) { throw new RuntimeException('Не определить тип'); }
    echo $name, ': ', $type, "\n";
}
Ожидаемый результат
pickup.txt: text/plain
instructions.html: text/html

Определитель создаётся до цикла и используется повторно. Каждый вызов всё равно анализирует содержимое. Текстовая памятка и HTML-инструкция требуют разных способов показа: HTML нельзя безусловно вставлять как доверенную разметку.

Перехватить ошибку собственной базыСамостоятельный пример
<?php
declare(strict_types=1);

try { new finfo(FILEINFO_MIME_TYPE, 'missing.magic'); }
catch (Exception $error) { echo "Cannot load configured database\n"; }
Ожидаемый результат
Cannot load configured database

Конструктор не возвращает false. Это отказ конфигурации сервиса, а не сообщение посетителю о плохом файле.

Сравните: finfo, finfo::file, finfo::buffer, finfo_set_flags, finfo_close. Тип, кодировка и границы определения.

finfo_fileОпределить тип файла по его содержимому, а не по суффиксу имени.

PHP 5.3+ / PECL fileinfo 0.1+ · fileinfo

finfo_file(finfo $finfo, string $filename, int $flags = FILEINFO_NONE, ?resource $context = null): string|false

Определить тип файла по его содержимому, а не по суффиксу имени.

Часть вызоваДоговор
finfoНастроенный объект finfo. До 8.1 процедурная функция принимала ресурс.
filenameПуть к анализируемому файлу. Строка пути не является содержимым. Для загруженного файла берут проверенный $_FILES[…]["tmp_name"], не клиентское name.
flagsНеобязательный ненулевой набор временно заменяет флаги объекта на один вызов, затем прежние восстанавливаются. FILEINFO_NONE = 0 здесь сохраняет текущие настройки; для постоянного сброса set_flags(FILEINFO_NONE).
contextКонтекст потока, nullable с 8.0. Может влиять на открытие через поддерживаемую обёртку. Не позволяйте посетителю выбирать произвольный URL для проверки: это создаёт сетевой запрос сервера.
ВозвратСтрока описания/типа/кодировки по флагам или false при ошибке. Не равняйте неизвестный application/octet-stream ошибке вызова.
ОшибкиНедоступный файл — предупреждение и false. Пустой путь — ValueError. Нулевой байт в пути с 8.5 даёт ValueError, раньше TypeError. Это не то же правило, что для нулевого байта в buffer.

В коде $ начинает имя переменной, = сохраняет возвращённое значение, скобки передают аргументы вызова. new finfo(...) создаёт настроенный объект; ->file(...) или ->buffer(...) вызывает его метод. === false проверяет именно неуспех, не любую пустую строку. throw new RuntimeException(...) останавливает обычный путь выполнения с объектом ошибки; catch перехватывает указанный тип, а finally завершает обязательную очистку даже при ошибке. Разбор try, catch и finally.

Данные → предположение о типе
  1. Файл document.jpg содержит Hello world
  2. libmagic проверяет содержимое по правилам
  3. MIME_TYPE возвращает text/plain
  4. Приложение отдельно решает, разрешён ли этот тип
Распознать обычный текстСамостоятельный пример
<?php
declare(strict_types=1);

$detector = new finfo(FILEINFO_MIME_TYPE);
$type = finfo_file($detector, 'document.jpg');
if ($type === false) { throw new RuntimeException('Cannot detect type'); }
echo $type, "\n";
Ожидаемый результат
text/plain

Файл назван .jpg, но его содержимое — текст. Имя не превратило его в изображение; MIME-тип остаётся эвристическим результатом, не полным разбором формата.

Запросить кодировку на один вызов, сохранив режим типаСамостоятельный пример
<?php
declare(strict_types=1);

$detector = new finfo(FILEINFO_MIME_TYPE);
echo finfo_file($detector, 'document.jpg', FILEINFO_MIME_ENCODING), "\n";
echo finfo_file($detector, 'document.jpg'), "\n";
echo finfo_file($detector, 'document.jpg', FILEINFO_NONE), "\n";
Ожидаемый результат
us-ascii
text/plain
text/plain

Второй и третий результаты показывают, что временный режим не остался у объекта. Переданный 0 не сбрасывает его в описательный режим.

Отличить неверный путь от ошибки распознаванияСамостоятельный пример
<?php
declare(strict_types=1);

$detector = new finfo(FILEINFO_MIME_TYPE);
try { $type = finfo_file($detector, "bad\0path"); }
catch (ValueError $error) { echo "Invalid path\n"; }
Ожидаемый результат
Invalid path

Пример рассчитан на PHP 8.5+. Нулевой байт отвергнут до открытия; раньше этот случай имел TypeError. Не убирайте такой байт молча, превращая исходное имя в другой путь.

У анализа пути тоже есть стоимость чтения и внутренней обработки. Ограничивайте допустимые размеры до тяжёлых операций; не используйте анализ каталогов/устройств как эквивалент приёма обычного файла. Полный путь приёма загрузки.

Сравните: finfo::buffer, finfo_set_flags, mime_content_type. Тип, кодировка и границы определения.

finfo_bufferОпределить тип данных, которые уже находятся в строке PHP.

PHP 5.3+ / PECL fileinfo 0.1+ · fileinfo

finfo_buffer(finfo $finfo, string $string, int $flags = FILEINFO_NONE, ?resource $context = null): string|false

Определить тип данных, которые уже находятся в строке PHP.

Часть вызоваДоговор
finfoНастроенный объект finfo. До 8.1 процедурная функция принимала ресурс.
stringСами бинарные данные в PHP-строке, не путь и не Base64-представление. Строка может содержать нулевые байты.
flagsНеобязательный ненулевой набор временно заменяет флаги объекта на один вызов, затем прежние восстанавливаются. FILEINFO_NONE = 0 здесь сохраняет текущие настройки; для постоянного сброса set_flags(FILEINFO_NONE).
contextИгнорируется; явная передача, включая null, deprecated с 8.5. Nullable с 8.0. В новом коде аргумент опускают.
ВозвратСтрока описания/типа/кодировки по флагам или false при ошибке. Не равняйте неизвестный application/octet-stream ошибке вызова.
ОшибкиОшибка распознавания может выдать E_WARNING и false. Тип аргумента должен соответствовать сигнатуре.

В коде $ начинает имя переменной, = сохраняет возвращённое значение, скобки передают аргументы вызова. new finfo(...) создаёт настроенный объект; ->file(...) или ->buffer(...) вызывает его метод. === false проверяет именно неуспех, не любую пустую строку. throw new RuntimeException(...) останавливает обычный путь выполнения с объектом ошибки; catch перехватывает указанный тип, а finally завершает обязательную очистку даже при ошибке. Разбор try, catch и finally.

Путь конкретного документа
  1. $contents содержит Pickup order 104
  2. buffer анализирует саму строку
  3. Возвращает text/plain
  4. Текст пока не преобразован и не проверен по бизнес-схеме
Классифицировать уже полученный текст памяткиСамостоятельный пример
<?php
declare(strict_types=1);

$detector = new finfo(FILEINFO_MIME_TYPE);
$contents = "Pickup order 104\n";
$type = finfo_buffer($detector, $contents);
if ($type === false) { throw new RuntimeException('Не определить тип'); }
echo 'Данные: ', $contents;
echo 'Формат: ', $type, "\n";
Ожидаемый результат
Данные: Pickup order 104
Формат: text/plain

buffer анализирует сами байты строки. Передача "pickup.txt" означала бы анализ букв имени, а не открытие файла. Для файла, который ещё лежит на диске, выбирайте file.

Запросить кодировку на один вызов, сохранив режим типаСамостоятельный пример
<?php
declare(strict_types=1);

$detector = new finfo(FILEINFO_MIME_TYPE);
echo finfo_buffer($detector, "Hello world\n", FILEINFO_MIME_ENCODING), "\n";
echo finfo_buffer($detector, "Hello world\n"), "\n";
echo finfo_buffer($detector, "Hello world\n", FILEINFO_NONE), "\n";
Ожидаемый результат
us-ascii
text/plain
text/plain

Второй и третий результаты показывают, что временный режим не остался у объекта. Переданный 0 не сбрасывает его в описательный режим.

Сами байты и их транспортное представление различаютсяСамостоятельный пример
<?php
declare(strict_types=1);

$detector = new finfo(FILEINFO_MIME_TYPE);
$bytes = hex2bin('47494638396101000100800000000000ffffff21f90401000000002c00000000010001000002024401003b');
if ($bytes === false) { throw new RuntimeException('Invalid fixed fixture'); }
echo finfo_buffer($detector, $bytes), "\n";
echo finfo_buffer($detector, base64_encode($bytes)), "\n";
Ожидаемый результат
image/gif
text/plain

GIF — небольшой собственный бинарный fixture. Base64 — уже другой набор текстовых байтов. Декодирование внешнего Base64 выполняют строго и с ограничением размера; результат MIME не заменяет полноценное декодирование изображения.

Если файл уже лежит на диске, file обычно позволяет не загружать весь документ в отдельную PHP-строку. buffer полезен для небольших уже полученных данных; не используйте file_get_contents большого файла только ради MIME-проверки. Полный путь приёма загрузки.

Сравните: finfo::file, finfo_set_flags, mime_content_type. Тип, кодировка и границы определения.

finfo::bufferОпределить тип данных, которые уже находятся в строке PHP.

PHP 5.3+ / PECL fileinfo 0.1+ · fileinfo

public function buffer(string $string, int $flags = FILEINFO_NONE, ?resource $context = null): string|false

Определить тип данных, которые уже находятся в строке PHP.

Часть вызоваДоговор
stringСами бинарные данные в PHP-строке, не путь и не Base64-представление. Строка может содержать нулевые байты.
flagsНеобязательный ненулевой набор временно заменяет флаги объекта на один вызов, затем прежние восстанавливаются. FILEINFO_NONE = 0 здесь сохраняет текущие настройки; для постоянного сброса set_flags(FILEINFO_NONE).
contextИгнорируется; явная передача, включая null, deprecated с 8.5. Nullable с 8.0. В новом коде аргумент опускают.
ВозвратСтрока описания/типа/кодировки по флагам или false при ошибке. Не равняйте неизвестный application/octet-stream ошибке вызова.
ОшибкиОшибка распознавания может выдать E_WARNING и false. Тип аргумента должен соответствовать сигнатуре.

В коде $ начинает имя переменной, = сохраняет возвращённое значение, скобки передают аргументы вызова. new finfo(...) создаёт настроенный объект; ->file(...) или ->buffer(...) вызывает его метод. === false проверяет именно неуспех, не любую пустую строку. throw new RuntimeException(...) останавливает обычный путь выполнения с объектом ошибки; catch перехватывает указанный тип, а finally завершает обязательную очистку даже при ошибке. Разбор try, catch и finally.

Путь конкретного документа
  1. $contents содержит Pickup order 104
  2. buffer анализирует саму строку
  3. Возвращает text/plain
  4. Текст пока не преобразован и не проверен по бизнес-схеме
Классифицировать уже полученный текст памяткиСамостоятельный пример
<?php
declare(strict_types=1);

$detector = new finfo(FILEINFO_MIME_TYPE);
$contents = "Pickup order 104\n";
$type = $detector->buffer($contents);
if ($type === false) { throw new RuntimeException('Не определить тип'); }
echo 'Данные: ', $contents;
echo 'Формат: ', $type, "\n";
Ожидаемый результат
Данные: Pickup order 104
Формат: text/plain

buffer анализирует сами байты строки. Передача "pickup.txt" означала бы анализ букв имени, а не открытие файла. Для файла, который ещё лежит на диске, выбирайте file.

Запросить кодировку на один вызов, сохранив режим типаСамостоятельный пример
<?php
declare(strict_types=1);

$detector = new finfo(FILEINFO_MIME_TYPE);
echo $detector->buffer("Hello world\n", FILEINFO_MIME_ENCODING), "\n";
echo $detector->buffer("Hello world\n"), "\n";
echo $detector->buffer("Hello world\n", FILEINFO_NONE), "\n";
Ожидаемый результат
us-ascii
text/plain
text/plain

Второй и третий результаты показывают, что временный режим не остался у объекта. Переданный 0 не сбрасывает его в описательный режим.

Сами байты и их транспортное представление различаютсяСамостоятельный пример
<?php
declare(strict_types=1);

$detector = new finfo(FILEINFO_MIME_TYPE);
$bytes = hex2bin('47494638396101000100800000000000ffffff21f90401000000002c00000000010001000002024401003b');
if ($bytes === false) { throw new RuntimeException('Invalid fixed fixture'); }
echo $detector->buffer($bytes), "\n";
echo $detector->buffer(base64_encode($bytes)), "\n";
Ожидаемый результат
image/gif
text/plain

GIF — небольшой собственный бинарный fixture. Base64 — уже другой набор текстовых байтов. Декодирование внешнего Base64 выполняют строго и с ограничением размера; результат MIME не заменяет полноценное декодирование изображения.

Если файл уже лежит на диске, file обычно позволяет не загружать весь документ в отдельную PHP-строку. buffer полезен для небольших уже полученных данных; не используйте file_get_contents большого файла только ради MIME-проверки. Полный путь приёма загрузки.

Сравните: finfo::file, finfo_set_flags, mime_content_type. Тип, кодировка и границы определения.

finfo_set_flagsПостоянно изменить формат определения для следующих вызовов этого объекта.

PHP 5.3+ / PECL fileinfo 0.1+ · fileinfo

finfo_set_flags(finfo $finfo, int $flags): true

Постоянно изменить формат определения для следующих вызовов этого объекта.

Часть вызоваДоговор
finfoНастроенный объект finfo; до 8.1 процедурный вызов принимал ресурс.
flagsОдин флаг или комбинация через |. Полностью заменяет предыдущие настройки, а не добавляет их автоматически.
ВозвратВсегда true при штатном вызове; это подтверждает применение настройки, не успешную классификацию будущего файла.
Общая ссылкаДве переменные с одним объектом видят одну настройку. Для двух независимых политик создайте два finfo.

В коде $ начинает имя переменной, = сохраняет возвращённое значение, скобки передают аргументы вызова. new finfo(...) создаёт настроенный объект; ->file(...) или ->buffer(...) вызывает его метод. === false проверяет именно неуспех, не любую пустую строку. throw new RuntimeException(...) останавливает обычный путь выполнения с объектом ошибки; catch перехватывает указанный тип, а finally завершает обязательную очистку даже при ошибке. Разбор try, catch и finally.

Меняется конфигурация объекта
  1. Было FILEINFO_MIME_TYPE
  2. set_flags(FILEINFO_MIME_ENCODING)
  3. Следующий buffer возвращает us-ascii
  4. Настройка сохраняется до следующей смены
Узнать предполагаемую кодировку вместо типаСамостоятельный пример
<?php
declare(strict_types=1);

$detector = new finfo(FILEINFO_MIME_TYPE);
$text = "Pickup order 104\n";
echo 'Тип: ', $detector->buffer($text), "\n";
finfo_set_flags($detector, FILEINFO_MIME_ENCODING);
echo 'Кодировка: ', $detector->buffer($text), "\n";
Ожидаемый результат
Тип: text/plain
Кодировка: us-ascii

set_flags заменяет постоянный режим объекта. Данные $text не перекодируются: изменился вопрос, на который отвечает определитель.

Получить тип и кодировку вместеСамостоятельный пример
<?php
declare(strict_types=1);

$detector = new finfo(FILEINFO_MIME_TYPE);
finfo_set_flags($detector, FILEINFO_MIME_TYPE | FILEINFO_MIME_ENCODING);
echo $detector->buffer("Привет\n"), "\n";
Ожидаемый результат
text/plain; charset=utf-8

Оператор | объединяет битовые флаги. FILEINFO_MIME — готовая константа той же комбинации. Для точного списка допустимых MIME удобнее MIME_TYPE, иначе charset станет частью сравниваемой строки.

Получить описание для диагностики и вернуть MIME-режимСамостоятельный пример
<?php
declare(strict_types=1);

$detector = new finfo(FILEINFO_MIME_TYPE);
$text = "Pickup order 104\n";
finfo_set_flags($detector, FILEINFO_NONE);
echo 'Описание: ', $detector->buffer($text), "\n";
finfo_set_flags($detector, FILEINFO_MIME_TYPE);
echo 'Для сравнения форматов: ', $detector->buffer($text), "\n";
Ожидаемый результат
Описание: ASCII text
Для сравнения форматов: text/plain

Точная свободная формулировка описания зависит от libmagic; здесь показан фактический результат учебного runtime. Для списка допустимых форматов используют стабильнее выраженный MIME_TYPE, а не сравнивают полное описание.

Сравните: finfo_open, finfo::buffer, finfo::file. Тип, кодировка и границы определения.

finfo::set_flagsПостоянно изменить формат определения для следующих вызовов этого объекта.

PHP 5.3+ / PECL fileinfo 0.1+ · fileinfo

public function set_flags(int $flags): true

Постоянно изменить формат определения для следующих вызовов этого объекта.

Часть вызоваДоговор
flagsОдин флаг или комбинация через |. Полностью заменяет предыдущие настройки, а не добавляет их автоматически.
ВозвратВсегда true при штатном вызове; это подтверждает применение настройки, не успешную классификацию будущего файла.
Общая ссылкаДве переменные с одним объектом видят одну настройку. Для двух независимых политик создайте два finfo.

В коде $ начинает имя переменной, = сохраняет возвращённое значение, скобки передают аргументы вызова. new finfo(...) создаёт настроенный объект; ->file(...) или ->buffer(...) вызывает его метод. === false проверяет именно неуспех, не любую пустую строку. throw new RuntimeException(...) останавливает обычный путь выполнения с объектом ошибки; catch перехватывает указанный тип, а finally завершает обязательную очистку даже при ошибке. Разбор try, catch и finally.

Меняется конфигурация объекта
  1. Было FILEINFO_MIME_TYPE
  2. set_flags(FILEINFO_MIME_ENCODING)
  3. Следующий buffer возвращает us-ascii
  4. Настройка сохраняется до следующей смены
Узнать предполагаемую кодировку вместо типаСамостоятельный пример
<?php
declare(strict_types=1);

$detector = new finfo(FILEINFO_MIME_TYPE);
$text = "Pickup order 104\n";
echo 'Тип: ', $detector->buffer($text), "\n";
$detector->set_flags(FILEINFO_MIME_ENCODING);
echo 'Кодировка: ', $detector->buffer($text), "\n";
Ожидаемый результат
Тип: text/plain
Кодировка: us-ascii

set_flags заменяет постоянный режим объекта. Данные $text не перекодируются: изменился вопрос, на который отвечает определитель.

Получить тип и кодировку вместеСамостоятельный пример
<?php
declare(strict_types=1);

$detector = new finfo(FILEINFO_MIME_TYPE);
$detector->set_flags(FILEINFO_MIME_TYPE | FILEINFO_MIME_ENCODING);
echo $detector->buffer("Привет\n"), "\n";
Ожидаемый результат
text/plain; charset=utf-8

Оператор | объединяет битовые флаги. FILEINFO_MIME — готовая константа той же комбинации. Для точного списка допустимых MIME удобнее MIME_TYPE, иначе charset станет частью сравниваемой строки.

Получить описание для диагностики и вернуть MIME-режимСамостоятельный пример
<?php
declare(strict_types=1);

$detector = new finfo(FILEINFO_MIME_TYPE);
$text = "Pickup order 104\n";
$detector->set_flags(FILEINFO_NONE);
echo 'Описание: ', $detector->buffer($text), "\n";
$detector->set_flags(FILEINFO_MIME_TYPE);
echo 'Для сравнения форматов: ', $detector->buffer($text), "\n";
Ожидаемый результат
Описание: ASCII text
Для сравнения форматов: text/plain

Точная свободная формулировка описания зависит от libmagic; здесь показан фактический результат учебного runtime. Для списка допустимых форматов используют стабильнее выраженный MIME_TYPE, а не сравнивают полное описание.

Сравните: finfo_open, finfo::buffer, finfo::file. Тип, кодировка и границы определения.

finfo_closeРаспознать устаревшее закрытие ресурса в старом проекте и убрать ненужный вызов.

PHP 5.3+ / PECL fileinfo 0.1+ · fileinfo

#[Deprecated(since: "8.5")] finfo_close(finfo $finfo): true

Распознать устаревшее закрытие ресурса в старом проекте и убрать ненужный вызов.

Часть вызоваДоговор
finfoВ современном PHP объект finfo, до 8.1 был ресурс.
ВозвратВсегда true; в PHP 8.1+ вызов не выполняет закрытие. Тип возврата true явно указан с 8.5, ранее bool.
СтатусDeprecated с PHP 8.5: объекты освобождаются автоматически. Удалите вызов в новом коде; unset убирает одну ссылку, другие могут удерживать объект.
ИсторияТаблица изменений относит ресурс→объект и no-op к 8.1. Вводный абзац текущей страницы упоминает 8.0; проверка официальных исходников PHP 8.0.30 (RETURN_RES) и 8.1.0 (RETURN_OBJ) подтверждает границу 8.1.

В коде $ начинает имя переменной, = сохраняет возвращённое значение, скобки передают аргументы вызова. new finfo(...) создаёт настроенный объект; ->file(...) или ->buffer(...) вызывает его метод. === false проверяет именно неуспех, не любую пустую строку. throw new RuntimeException(...) останавливает обычный путь выполнения с объектом ошибки; catch перехватывает указанный тип, а finally завершает обязательную очистку даже при ошибке. Разбор try, catch и finally.

Старая операция утратила смысл
  1. Раньше finfo_open возвращал ресурс
  2. С PHP 8.1 возвращается finfo
  3. Срок жизни управляется ссылками на объект
  4. finfo_close устарел в 8.5 и не нужен
Найти устаревание без вызова функцииСамостоятельный пример
<?php
declare(strict_types=1);

$reflection = new ReflectionFunction('finfo_close');
$attributes = $reflection->getAttributes(Deprecated::class);
echo $attributes[0]->newInstance()->since, "\n";
Ожидаемый результат
8.5

Это пример PHP 8.5 с метаданными. Он не вызывает устаревшую функцию и не подавляет предупреждение; на старом PHP атрибута может не быть.

Получить формат внутри функции без устаревшего закрытияСамостоятельный пример
<?php
declare(strict_types=1);

function detectDocumentType(string $text): string
{
    $detector = new finfo(FILEINFO_MIME_TYPE);
    $type = $detector->buffer($text);
    if ($type === false) { throw new RuntimeException('Не определить тип'); }
    return $type;
}
echo 'Памятка заказа 104: ', detectDocumentType("Pickup order 104\n"), "\n";
Ожидаемый результат
Памятка заказа 104: text/plain

После возврата локальная ссылка $detector исчезает, объект освобождается, если его больше никто не удерживает. finfo_close не нужен в PHP8.1+ и deprecated с8.5. Явный unset после каждого файла тоже не обязателен.

Сравните: finfo_open, finfo, unset. Тип, кодировка и границы определения.

mime_content_typeУзнать MIME-тип локального файла или доступного читаемого потока одним вызовом.

PHP 4.3+ · fileinfo

mime_content_type(resource|string $filename): string|false

Узнать MIME-тип локального файла или доступного читаемого потока одним вызовом.

Часть вызоваДоговор
filenameПуть к файлу либо ресурс потока. Строка — путь, не содержимое.
ВозвратMIME-тип, например text/plain/application/octet-stream; false при неуспехе и E_WARNING.
Ошибки аргументаВ проверенном PHP 8.5.11 пустой путь даёт ValueError, путь с NUL — TypeError. Не переносите правило finfo_file автоматически: там с 8.5 NUL даёт ValueError.
ПотокРеализация пытается перейти к началу и восстановить позицию. Для перематываемого собственного потока это проверено; для сетевого/неперематываемого потока такую гарантию давать нельзя.
АльтернативаДля серии файлов finfo позволяет один раз создать объект и выбрать режим. MIME сам по себе не проверяет безопасность содержимого.

В коде $ начинает имя переменной, = сохраняет возвращённое значение, скобки передают аргументы вызова. new finfo(...) создаёт настроенный объект; ->file(...) или ->buffer(...) вызывает его метод. === false проверяет именно неуспех, не любую пустую строку. throw new RuntimeException(...) останавливает обычный путь выполнения с объектом ошибки; catch перехватывает указанный тип, а finally завершает обязательную очистку даже при ошибке. Разбор try, catch и finally.

Путь → тип
  1. report.txt — путь к данным
  2. Функция открывает и анализирует содержимое
  3. Возвращается строка text/plain
  4. Решение о допустимости принимает приложение
Прочитать MIME-тип известного текстового файлаСамостоятельный пример
<?php
declare(strict_types=1);

$mime = mime_content_type('report.txt');
if ($mime === false) { throw new RuntimeException('Cannot detect type'); }
echo $mime, "\n";
Ожидаемый результат
text/plain

Здесь нет загрузки от посетителя: report.txt — собственный учебный файл. Для формы нужен tmp_name после проверки структуры $_FILES и кода загрузки.

Исследовать собственный перематываемый потокСамостоятельный пример
<?php
declare(strict_types=1);

$stream = fopen('php://temp', 'w+b');
if ($stream === false) { throw new RuntimeException('Cannot open temporary stream'); }
try {
    fwrite($stream, "Hello world\n");
    fseek($stream, 3);
    echo mime_content_type($stream), "\n";
    echo ftell($stream), "\n";
} finally { fclose($stream); }
Ожидаемый результат
text/plain
3

После распознавания собственный поток остался на позиции 3. Это проверка конкретного перематываемого потока; она не означает поддержку такой семантики у любого ресурса/URL.

Сравните: finfo::file, finfo::buffer, fopen. Тип, кодировка и границы определения.

finfoОбъединить базу правил и настройки определения типа в многократно используемом объекте.

PHP 5.3+ / PECL fileinfo 0.1+ · fileinfo

class finfo { __construct(int $flags = FILEINFO_NONE, ?string $magic_database = null); buffer(string $string, int $flags = FILEINFO_NONE, ?resource $context = null): string|false; file(string $filename, int $flags = FILEINFO_NONE, ?resource $context = null): string|false; set_flags(int $flags): true; }

Объединить базу правил и настройки определения типа в многократно используемом объекте.

Часть вызоваДоговор
Созданиеnew finfo(...), либо finfo_open(...) с проверкой false.
Методыbuffer — готовые байты, file — путь, set_flags — постоянная смена режима. Полные контракты каждого доступны ниже по ссылкам.
СостояниеНастройка принадлежит объекту. Отдельные объекты могут иметь разные режимы; обычное присваивание переменной не копирует объект.
ГраницаЭвристический определитель формата, не конвертер, антивирус, декодер изображения или проверка доступа.

В коде $ начинает имя переменной, = сохраняет возвращённое значение, скобки передают аргументы вызова. new finfo(...) создаёт настроенный объект; ->file(...) или ->buffer(...) вызывает его метод. === false проверяет именно неуспех, не любую пустую строку. throw new RuntimeException(...) останавливает обычный путь выполнения с объектом ошибки; catch перехватывает указанный тип, а finally завершает обязательную очистку даже при ошибке. Разбор try, catch и finally.

Объект хранит выбранное правило
  1. $types настроен на MIME_TYPE
  2. $encoding настроен на MIME_ENCODING
  3. Одинаковые байты передаются двум объектам
  4. Результаты text/plain и us-ascii отвечают на разные вопросы
Два независимых определителя для двух задачСамостоятельный пример
<?php
declare(strict_types=1);

$types = new finfo(FILEINFO_MIME_TYPE);
$encoding = new finfo(FILEINFO_MIME_ENCODING);
$contents = "Hello world\n";
echo $types->buffer($contents), "\n", $encoding->buffer($contents), "\n";
Ожидаемый результат
text/plain
us-ascii

Первый результат отвечает «какой формат», второй — «какая предполагается кодировка». Ни одна операция не перекодировала contents.

Две переменные могут менять один определительСамостоятельный пример
<?php
declare(strict_types=1);

$detector = new finfo(FILEINFO_MIME_TYPE);
$same = $detector;
$same->set_flags(FILEINFO_MIME_ENCODING);
echo $detector->buffer("Hello world\n"), "\n";
var_dump($same === $detector);
Ожидаемый результат
us-ascii
bool(true)

Изменение видно через обе переменные, потому что объект один. Чтобы соседние операции не меняли друг другу политику, передавайте временный флаг на вызов или создайте отдельные объекты.

Сравните: finfo::__construct, finfo::buffer, finfo::file, finfo::set_flags. Тип, кодировка и границы определения.

Источники и обсуждения

Код и руководство с собой

Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.

Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.

Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.