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

Дерево руководства
Глава 108 · После первых SELECT и массива результата
Старый MySQL API: перенести метаданные полей и списки таблиц
Имена и aliases, типы и битовые флаги, символы и байты, курсор описаний, каталог пустой таблицы и видимость схемы. Двенадцать исторических контрактов с современными программами.
Данные, описание результата и каталог — три разных задачи
При переносе старого сайта мало заменить mysql_query на mysqli_query. Генератор CSV или редактор форм мог использовать описание колонок: имя, тип, ширину, ключи. Начнём с отчёта о кружке, у которого имя в таблице name, а заголовок результата product_name. Нужен понятный результат: данные остаются прежними, а код правильно отличает имя для вывода от структуры хранения.
| Уровень | Что содержит | Как читаем сейчас |
|---|---|---|
| Данные строки | 1, Кружка, 250.00 | fetch_row / fetch_assoc |
| Описание SELECT | name=product_name, orgname=name, table=p | fetch_field / fetch_fields |
| Схема таблицы | VARCHAR(40), NOT NULL, PRIMARY KEY | INFORMATION_SCHEMA / SHOW COLUMNS |
| Список объектов | Доступные базы/таблицы | SCHEMATA / TABLES / SHOW |
- Таблица хранит name=Кружка
- SELECT p.name AS product_name выбирает значение и даёт ему заголовок
- Metadata описывает заголовок и происхождение
- Fetch читает само значение Кружка
Метаданные — описание, похожее на подписи колонок в бланке; это не сами заполненные строки. Аналогия ограничена: вычисляемое выражение SELECT может не иметь единственного исходного столбца. Полезно знать массивы и таблицы, типы и связи, но смысл каждого обращения показан в малом фрагменте перед полной программой.
Как запустить современный пример и прочитать отчёт
Полные программы выполняются на PHP 8.2+ с mysqli/mysqlnd и отдельной локальной учебной базой MySQL 8.4/InnoDB. Контрольное окружение — PHP 8.5.11/MySQL 8.4.13. Устаревшее ext/mysql не устанавливается, PHP 5 не нужен. Начальную настройку см. в подключении PHP к MySQL.
Распакуйте архив, задайте PHPMAN_MYSQL_HOST, PHPMAN_MYSQL_PORT, PHPMAN_MYSQL_DATABASE, PHPMAN_MYSQL_USER, PHPMAN_MYSQL_PASSWORD в окружении своего терминала и выполните php example.php. На контрольном стенде используется localhost:33070; у вас порт может быть другим. Реквизиты в архив не входят. README и mysql108-metadata-helper.php включены в каждый архив.
Создаются только собственные mysql108_meta_* и mysql108_diag_* таблицы в выделенной базе. Занятое имя вызывает отказ CREATE и не попадает в список очистки. finally удаляет только успешно созданные этим запуском таблицы; после аварийного завершения процесса они могут остаться. Запускать это в базе рабочего сайта не следует. Права на базу ограничены; CREATE/DROP DATABASE ни один пример не выполняет.
- example.php выполняет современные запросы MySQLi
- result.json: точные таблицы результата
- observations.json: реальные версии, ID и счётчики
- result.html: те же таблицы и наблюдения, удобно читать в браузере
- metrics.json: локальные проверки и контрольные суммы
Версии, ID и показания счётчиков не придумываются: они поступают из текущего запуска и показаны в result.html. В тексте главы таблица «Что получится» содержит устойчивые свойства и учебные данные; переменные показания находятся в сохранённом фактическом результате. Это CLI-проверка PHP/MySQL, не отправка HTML-формы и не тест HTTP.
Отличить заголовок отчёта от исходного столбца
Старый экспорт строит заголовки через mysql_field_name, а затем пытается по этим же строкам найти исходные поля таблицы. После AS product_name это уже разные имена. Покажем и удобный заголовок, и происхождение значения.
Исходные данные
Таблица mysql108_meta_aliases
| id | name | price |
|---|---|---|
| 1 | Кружка | 250.00 |
Что получится
Имена выходных и исходных полей
| name | orgname | table | orgtable |
|---|---|---|---|
| product_id | id | p | mysql108_meta_aliases |
| product_name | name | p | mysql108_meta_aliases |
| price | price | p | mysql108_meta_aliases |
Данные отчёта
| product_id | product_name | price |
|---|---|---|
| 1 | Кружка | 250.00 |
Малый фрагмент: сначала смысл действия
$result = $db->query('SELECT p.name AS product_name FROM mysql108_meta_aliases AS p');
$field = $result->fetch_field();
echo $field->name; // product_name
echo $field->orgname; // nameЭто фрагмент внутри показанного сценария: $db — уже установленное соединение; $result — результат соответствующего SELECT. Полный запуск ниже самостоятельно создаёт нужные входные таблицы. Если показан SQL, его выполняет query/execute_query из полной программы.
Результат SELECT имеет свою структуру: три выходных поля располагаются в указанном запросом порядке. Объект metadata описывает столбец, а fetch_row читает значения строки. AS меняет name, но orgname хранит исходное имя обычного столбца; alias таблицы p виден в table, исходное имя — в orgtable. Стрелка -> обращается к свойству объекта поля. Вызов fetch_fields возвращает массив таких объектов, по одному на выбранный столбец.
- Таблица mysql108_meta_aliases: name = Кружка
- SQL: p.name AS product_name
- Поле результата: name=product_name; orgname=name
- HTML/CSV: заголовок product_name; значение Кружка
Не определяйте SQL для UPDATE прямо по metadata клиентского отчёта: выражения, JOIN и вычисляемые поля могут не иметь единственной исходной колонки. Для вычисления price*2 поля table/orgtable могут быть пустыми. Сначала задайте разрешённую модель редактирования. Для денежных данных SQL DECIMAL остаётся строковым десятичным значением в этом чтении; метаданные не превращают PHP float в точную валюту.
Ошибки и ограничения
Не путайте регистр имени, alias и название физической таблицы. Тип mysqli — числовой MYSQLI_TYPE_*; старые проверки type === "int" не перенесутся автоматически. PHP-тип прочитанного значения и SQL-тип — разные сведения.
Полная самостоятельная программа PHP 8 и входные файлы
<?php
declare(strict_types=1);
require __DIR__.'/mysql108-metadata-helper.php';
$db=legacy108Connect();$other=null;$created=[];$blocks=[];$checks=[];$observations=[];
try {
legacy108Create($db,$created,'mysql108_meta_aliases','id INT PRIMARY KEY, name VARCHAR(40) NOT NULL, price DECIMAL(8,2) NOT NULL');
$db->query("INSERT INTO mysql108_meta_aliases VALUES(1,'Кружка',250.00)");
$result=$db->query('SELECT p.id AS product_id,p.name AS product_name,p.price FROM mysql108_meta_aliases AS p');
$fields=$result->fetch_fields();$rows=[];foreach($fields as $f){$rows[]=[$f->name,$f->orgname,$f->table,$f->orgtable];}
$data=$result->fetch_row();$result->free();
$blocks=[legacy108Block('Имена выходных и исходных полей',['name','orgname','table','orgtable'],$rows),legacy108Block('Данные отчёта',['product_id','product_name','price'],[array_map('strval',$data)])];
$checks=['three_fields'=>count($fields)===3,'alias_and_origin'=>$rows[1]===['product_name','name','p','mysql108_meta_aliases'],'data_preserved'=>(string)$data[0]==='1'&&$data[1]==='Кружка'];
$observations=[['Тип id из metadata',(string)$fields[0]->type],['Тип price из metadata',(string)$fields[2]->type]];
legacy108Report('mysql108-meta-aliases',$blocks,$checks,$observations,$db,[]);
} finally {legacy108Cleanup($db,$other,$created);}
echo "mysql108-meta-aliases: saved result.html and result.json\n";
Ожидаемый результат
mysql108-meta-aliases: saved result.html and result.json
Код использует mysqli, создаёт показанные учебные данные и сохраняет реальные result.html/result.json/observations.json. Уведомление консоли сообщает только о сохранении; полезный результат — таблицы выше и фактический HTML-файл. Helper и README включены в архив.
Скачать таблицы JSON · Открыть фактический результат · Скачать реальные наблюдения
Попробуйте сами. Добавьте p.price*2 AS double_price. В новом результате отдельно покажите name/orgname/table/orgtable этого выражения. Не обещайте, что по вычислению можно автоматически восстановить один редактируемый столбец.
Перенести строковые флаги в явные проверки битов
В старом редакторе форма ищет слова primary_key и not_null в строке mysql_field_flags. После перехода mysqli возвращает число. Из этого числа нужно извлечь конкретные свойства, сохранив nullable-поле заметки.
Исходные данные
Объявленная схема
| Поле | Определение |
|---|---|
| id | INT UNSIGNED PRIMARY KEY AUTO_INCREMENT |
| sku | VARCHAR(12) NOT NULL UNIQUE |
| note | VARCHAR(30) NULL |
Что получится
Проверяем свойства, а не всю числовую маску
| Столбец | Свойство | Есть |
|---|---|---|
| id | PRIMARY KEY | да |
| id | UNSIGNED | да |
| id | AUTO_INCREMENT | да |
| sku | NOT NULL | да |
| sku | UNIQUE | да |
| note | NOT NULL | нет |
Малый фрагмент: сначала смысл действия
$field = $result->fetch_field_direct(0);
$isPrimary = ($field->flags & MYSQLI_PRI_KEY_FLAG) !== 0;Это фрагмент внутри показанного сценария: $db — уже установленное соединение; $result — результат соответствующего SELECT. Полный запуск ниже самостоятельно создаёт нужные входные таблицы. Если показан SQL, его выполняет query/execute_query из полной программы.
Число flags — битовая маска: отдельным свойствам соответствуют отдельные биты. Операция & оставляет общие биты двух чисел; сравнение !== 0 означает «нужный бит установлен». MYSQLI_PRI_KEY_FLAG — именованная маска PRIMARY KEY. В отличие от равенства всей маске, эта проверка продолжает работать, если сервер сообщает и другие свойства поля. Полная числовая маска сохранена в наблюдениях, но договор примера проверяет только выбранные признаки.
ID одновременно PRIMARY KEY, UNSIGNED и AUTO_INCREMENT. SKU обязателен и уникален. Note допускает NULL, поэтому NOT_NULL_FLAG у него отсутствует. Битовая маска описывает серверную структуру, а не все правила формы: корректность артикула, разрешённые переходы статуса и права пользователя задаются приложением. UNIQUE допускает разные правила для NULL; здесь SKU явно NOT NULL.
Ошибки и ограничения
Не передавайте flags в explode и не сравнивайте всё число с одним MYSQLI_*_FLAG. Смысл multi-column индекса сложнее одного поля; для полного состава индекса нужен отдельный запрос к каталогу. Для nullable-поля отсутствие NOT NULL не означает, что пустая строка равна NULL.
Полная самостоятельная программа PHP 8 и входные файлы
<?php
declare(strict_types=1);
require __DIR__.'/mysql108-metadata-helper.php';
$db=legacy108Connect();$other=null;$created=[];$blocks=[];$checks=[];$observations=[];
try {
legacy108Create($db,$created,'mysql108_meta_flags','id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, sku VARCHAR(12) NOT NULL UNIQUE, note VARCHAR(30) NULL');
$db->query("INSERT INTO mysql108_meta_flags(sku,note) VALUES('A-100',NULL)");
$result=$db->query('SELECT id,sku,note FROM mysql108_meta_flags');$f=$result->fetch_fields();$result->free();
$tests=[['id','PRIMARY KEY',($f[0]->flags&MYSQLI_PRI_KEY_FLAG)!==0],['id','UNSIGNED',($f[0]->flags&MYSQLI_UNSIGNED_FLAG)!==0],['id','AUTO_INCREMENT',($f[0]->flags&MYSQLI_AUTO_INCREMENT_FLAG)!==0],['sku','NOT NULL',($f[1]->flags&MYSQLI_NOT_NULL_FLAG)!==0],['sku','UNIQUE',($f[1]->flags&MYSQLI_UNIQUE_KEY_FLAG)!==0],['note','NOT NULL',($f[2]->flags&MYSQLI_NOT_NULL_FLAG)!==0]];
$rows=array_map(fn($x)=>[$x[0],$x[1],legacy108Yes($x[2])],$tests);
$blocks=[legacy108Block('Проверяем свойства, а не всю числовую маску',['Столбец','Свойство','Есть'],$rows)];
$checks=['primary'=>$tests[0][2],'unsigned'=>$tests[1][2],'auto'=>$tests[2][2],'required'=>$tests[3][2],'unique'=>$tests[4][2],'nullable'=>!$tests[5][2]];
foreach($f as $field){$observations[]=[$field->name.' raw flags',(string)$field->flags];}
legacy108Report('mysql108-meta-flags',$blocks,$checks,$observations,$db,[]);
} finally {legacy108Cleanup($db,$other,$created);}
echo "mysql108-meta-flags: saved result.html and result.json\n";
Ожидаемый результат
mysql108-meta-flags: saved result.html and result.json
Код использует mysqli, создаёт показанные учебные данные и сохраняет реальные result.html/result.json/observations.json. Уведомление консоли сообщает только о сохранении; полезный результат — таблицы выше и фактический HTML-файл. Helper и README включены в архив.
Скачать таблицы JSON · Открыть фактический результат · Скачать реальные наблюдения
Попробуйте сами. Сделайте note NOT NULL DEFAULT "" и сравните только её NOT_NULL_FLAG. Затем объясните, почему обязательность столбца не проверяет непустой пользовательский текст.
Не принять байты поля за maxlength формы
Разработчик автоматически подставляет length из metadata в maxlength HTML-поля и получает 48 вместо ожидаемых 12. Разделим вместимость столбца в символах, предел в байтах и байты конкретного значения.
Исходные данные
Два значения
| label |
|---|
| Кот |
| AB |
Что получится
Договор VARCHAR(12) с utf8mb4
| Максимум символов | Максимум байтов |
|---|---|
| 12 | 48 |
Фактические значения
| label | CHAR_LENGTH | Байты полученной строки |
|---|---|---|
| Кот | 3 | 6 |
| AB | 2 | 2 |
Малый фрагмент: сначала смысл действия
SELECT CHARACTER_MAXIMUM_LENGTH, CHARACTER_OCTET_LENGTH
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'mysql108_meta_widths' AND COLUMN_NAME = 'label';Это фрагмент внутри показанного сценария: $db — уже установленное соединение; $result — результат соответствующего SELECT. Полный запуск ниже самостоятельно создаёт нужные входные таблицы. Если показан SQL, его выполняет query/execute_query из полной программы.
VARCHAR(12) с utf8mb4 допускает до 12 символов, для которых может потребоваться до 48 байтов. INFORMATION_SCHEMA.COLUMNS сообщает CHARACTER_MAXIMUM_LENGTH и CHARACTER_OCTET_LENGTH раздельно. В значении Кот три символа и шесть UTF-8 байтов; AB содержит два и два. CHAR_LENGTH выполняется сервером над значением, а result->lengths сообщает байтовую длину текущей уже прочитанной строки результата.
mysqli metadata length — ширина поля результата в байтах; она зависит и от кодировки соединения. Она не равна длине текущего значения. max_length с PHP 8.1 всегда 0: старый код, рассчитывающий по нему ширину отчёта, нужно пересмотреть. Даже ограничение HTML maxlength не является универсально идентичным MySQL CHAR_LENGTH: браузер считает кодовые единицы UTF-16, а пользовательский видимый символ может состоять из нескольких кодовых точек. Серверная проверка договора обязательна.
Ошибки и ограничения
Не делите любую длину на 4: типы, бинарные поля и кодировки различаются. Для нужной таблицы явно ограничивайте TABLE_SCHEMA и TABLE_NAME, иначе одноимённые таблицы разных баз смешаются. Максимум фактически полученных строк считайте по выбранной выборке, а не считайте max_length готовой статистикой.
Полная самостоятельная программа PHP 8 и входные файлы
<?php
declare(strict_types=1);
require __DIR__.'/mysql108-metadata-helper.php';
$db=legacy108Connect();$other=null;$created=[];$blocks=[];$checks=[];$observations=[];
try {
legacy108Create($db,$created,'mysql108_meta_widths','id INT PRIMARY KEY, label VARCHAR(12)');
$db->query("INSERT INTO mysql108_meta_widths VALUES(1,'Кот'),(2,'AB')");
$schema=legacy108Read($db,'SELECT CHARACTER_MAXIMUM_LENGTH,CHARACTER_OCTET_LENGTH FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=? AND COLUMN_NAME=?',['mysql108_meta_widths','label'])[0];
$result=$db->query('SELECT label,CHAR_LENGTH(label) FROM mysql108_meta_widths ORDER BY id');$field=$result->fetch_field_direct(0);$rows=[];
while($row=$result->fetch_row()){$lengths=$result->lengths;$rows[]=[$row[0],(string)$row[1],(string)$lengths[0]];}$result->free();
$blocks=[legacy108Block('Договор VARCHAR(12) с utf8mb4',['Максимум символов','Максимум байтов'],[$schema]),legacy108Block('Фактические значения',['label','CHAR_LENGTH','Байты полученной строки'],$rows)];
$checks=['schema_characters'=>$schema[0]==='12','schema_bytes'=>$schema[1]==='48','unicode'=>$rows[0]===['Кот','3','6'],'ascii'=>$rows[1]===['AB','2','2']];
$observations=[['mysqli metadata length',(string)$field->length],['mysqli metadata max_length (PHP 8.1+)',(string)$field->max_length]];
legacy108Report('mysql108-meta-widths',$blocks,$checks,$observations,$db,[]);
} finally {legacy108Cleanup($db,$other,$created);}
echo "mysql108-meta-widths: saved result.html and result.json\n";
Ожидаемый результат
mysql108-meta-widths: saved result.html and result.json
Код использует mysqli, создаёт показанные учебные данные и сохраняет реальные result.html/result.json/observations.json. Уведомление консоли сообщает только о сохранении; полезный результат — таблицы выше и фактический HTML-файл. Helper и README включены в архив.
Скачать таблицы JSON · Открыть фактический результат · Скачать реальные наблюдения
Попробуйте сами. Добавьте строку с emoji и сравните CHAR_LENGTH, OCTET_LENGTH и PHP strlen. Затем ограничьте выборку одной строкой и объясните, почему схема VARCHAR(12) при этом не изменилась.
Практический вопрос: Why does fetch_fields length differ from the declared CHAR/VARCHAR length?. Разработчик получает ширину в байтах и пытается использовать её как maxlength формы. Наш пример отдельно показывает символы схемы, максимальные байты и длину фактического UTF-8 значения. Обсуждение задаёт ситуацию; семантика сверена с PHP/MySQL, программа и её учебные данные написаны отдельно.
Перемещаться по полям, не теряя строки результата
Старый генератор отчётов сначала читает первое описание поля, затем переходит к третьему. При переносе легко принять field_seek за перемещение по строкам. Небольшой результат позволяет увидеть оба независимых указателя.
Исходные данные
Результат SELECT
| id | sku | title |
|---|---|---|
| 7 | A-100 | Кружка |
Что получится
Отдельный курсор метаданных
| Действие | Результат |
|---|---|
| fetch_field() | id |
| field_seek(2), затем fetch_field() | title |
| fetch_field_direct(1) | sku |
| fetch_field() после конца | false |
| Первое поле первой строки | 7 |
Малый фрагмент: сначала смысл действия
$result->field_seek(2); // Номер третьего столбца, не третьей строки.
$field = $result->fetch_field();
echo $field->name; // titleЭто фрагмент внутри показанного сценария: $db — уже установленное соединение; $result — результат соответствующего SELECT. Полный запуск ниже самостоятельно создаёт нужные входные таблицы. Если показан SQL, его выполняет query/execute_query из полной программы.
Нумерация полей начинается с нуля: id — 0, sku — 1, title — 2. fetch_field без номера берёт описание у текущего указателя и продвигает его. field_seek(2) переставляет только указатель метаданных; следующий fetch_field читает title. fetch_field_direct(1) обращается к конкретному полю, не меняя этот указатель. После конца fetch_field возвращает false. При этом первое чтение строки по-прежнему даёт id=7.
data_seek относится к строкам буферизованного результата, field_seek — к описаниям столбцов. Массив fetch_fields часто проще ручного курсора, если нужны все заголовки: foreach перебирает уже явный набор объектов. Прямой индекс полезен, если схема SELECT известна и нужен один столбец.
Ошибки и ограничения
Проверяйте границу 0 <= offset < field_count до доступа. Старое предупреждение или false для неправильного offset не следует механически переносить в современный код: mysqli может отклонить неверный аргумент исключением. Курсор метаданных не листает товары и не отменяет запрос.
Полная самостоятельная программа PHP 8 и входные файлы
<?php
declare(strict_types=1);
require __DIR__.'/mysql108-metadata-helper.php';
$db=legacy108Connect();$other=null;$created=[];$blocks=[];$checks=[];$observations=[];
try {
legacy108Create($db,$created,'mysql108_meta_cursor','id INT PRIMARY KEY, sku VARCHAR(12), title VARCHAR(30)');
$db->query("INSERT INTO mysql108_meta_cursor VALUES(7,'A-100','Кружка')");
$result=$db->query('SELECT id,sku,title FROM mysql108_meta_cursor');
$first=$result->fetch_field()->name;$result->field_seek(2);$third=$result->fetch_field()->name;
$direct=$result->fetch_field_direct(1)->name;$end=$result->fetch_field();$row=$result->fetch_row();$result->free();
$blocks=[legacy108Block('Отдельный курсор метаданных',['Действие','Результат'],[['fetch_field()',$first],['field_seek(2), затем fetch_field()',$third],['fetch_field_direct(1)',$direct],['fetch_field() после конца',$end===false?'false':'unexpected'],['Первое поле первой строки',(string)$row[0]]])];
$checks=['first'=>$first==='id','seek'=>$third==='title','direct'=>$direct==='sku','end'=>$end===false,'rows_not_moved'=>(string)$row[0]==='7'];
legacy108Report('mysql108-meta-cursor',$blocks,$checks,$observations,$db,[]);
} finally {legacy108Cleanup($db,$other,$created);}
echo "mysql108-meta-cursor: saved result.html and result.json\n";
Ожидаемый результат
mysql108-meta-cursor: saved result.html and result.json
Код использует mysqli, создаёт показанные учебные данные и сохраняет реальные result.html/result.json/observations.json. Уведомление консоли сообщает только о сохранении; полезный результат — таблицы выше и фактический HTML-файл. Helper и README включены в архив.
Скачать таблицы JSON · Открыть фактический результат · Скачать реальные наблюдения
Попробуйте сами. Переставьте SELECT в порядок title,id,sku и заново подпишите индексы. Исправьте только намеренную точку обращения, а затем покажите вариант foreach(fetch_fields()) без жёсткого номера.
Получить схему таблицы, даже если в ней нет товаров
Импортёр должен проверить названия и обязательность полей до первой загрузки. В новой таблице ещё нет товаров, поэтому читать первую строку ради определения схемы бессмысленно. Получим описание из каталога.
Исходные данные
План создания
| id | name | qty |
|---|---|---|
| INT PRIMARY KEY | VARCHAR(12) NOT NULL | INT NOT NULL DEFAULT 0 |
Что получится
Описание пустой таблицы
| COLUMN_NAME | DATA_TYPE | IS_NULLABLE | COLUMN_KEY |
|---|---|---|---|
| id | int | NO | PRI |
| name | varchar | NO | |
| qty | int | NO |
Данные и описание — разные результаты
| Показатель | Количество |
|---|---|
| Строк данных | 0 |
| Столбцов по SHOW COLUMNS | 3 |
Малый фрагмент: сначала смысл действия
SHOW COLUMNS FROM mysql108_meta_catalog;Это фрагмент внутри показанного сценария: $db — уже установленное соединение; $result — результат соответствующего SELECT. Полный запуск ниже самостоятельно создаёт нужные входные таблицы. Если показан SQL, его выполняет query/execute_query из полной программы.
SHOW COLUMNS возвращает строки-описания: Field, Type, Null, Key, Default, Extra. Это обычная таблица результата, а не специальный старый resource mysql_list_fields. INFORMATION_SCHEMA.COLUMNS даёт именованные колонки каталога; фильтр TABLE_SCHEMA=DATABASE() закрепляет выбранную базу, TABLE_NAME=? получает имя как значение параметра, ORDER BY ORDINAL_POSITION сохраняет порядок определения полей.
Пустой SELECT id,name,qty возвращает ноль строк данных, но схема всё равно имеет три столбца. Для отчёта по произвольному SELECT подходят fetch_fields; для точного определения таблицы — каталог или SHOW COLUMNS. DATA_TYPE даёт базовое имя вроде varchar, COLUMN_TYPE — более подробное объявление. COLUMN_KEY — краткая подсказка, а не полное описание составных индексов или всех ограничений.
Ошибки и ограничения
Знак ? в запросе к INFORMATION_SCHEMA подставляет значение TABLE_NAME, а не SQL-идентификатор. В SHOW COLUMNS FROM ? так подставить имя таблицы нельзя. При динамическом FROM выбирайте имя из разрешённого списка; в самостоятельной программе имя фиксировано.
Полная самостоятельная программа PHP 8 и входные файлы
<?php
declare(strict_types=1);
require __DIR__.'/mysql108-metadata-helper.php';
$db=legacy108Connect();$other=null;$created=[];$blocks=[];$checks=[];$observations=[];
try {
legacy108Create($db,$created,'mysql108_meta_catalog','id INT PRIMARY KEY, name VARCHAR(12) NOT NULL, qty INT NOT NULL DEFAULT 0');
$rows=legacy108Read($db,'SELECT COLUMN_NAME,DATA_TYPE,IS_NULLABLE,COLUMN_KEY FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=? ORDER BY ORDINAL_POSITION',['mysql108_meta_catalog']);
$empty=legacy108Read($db,'SELECT id,name,qty FROM mysql108_meta_catalog');
$show=legacy108Read($db,'SHOW COLUMNS FROM mysql108_meta_catalog');
$blocks=[legacy108Block('Описание пустой таблицы',['COLUMN_NAME','DATA_TYPE','IS_NULLABLE','COLUMN_KEY'],$rows),legacy108Block('Данные и описание — разные результаты',['Показатель','Количество'],[['Строк данных',(string)count($empty)],['Столбцов по SHOW COLUMNS',(string)count($show)]])];
$checks=['empty'=>$empty===[],'three_columns'=>count($rows)===3,'ordered_names'=>array_column($rows,0)===['id','name','qty'],'show_agrees'=>array_column($show,0)===array_column($rows,0)];
legacy108Report('mysql108-meta-catalog',$blocks,$checks,$observations,$db,[]);
} finally {legacy108Cleanup($db,$other,$created);}
echo "mysql108-meta-catalog: saved result.html and result.json\n";
Ожидаемый результат
mysql108-meta-catalog: saved result.html and result.json
Код использует mysqli, создаёт показанные учебные данные и сохраняет реальные result.html/result.json/observations.json. Уведомление консоли сообщает только о сохранении; полезный результат — таблицы выше и фактический HTML-файл. Helper и README включены в архив.
Скачать таблицы JSON · Открыть фактический результат · Скачать реальные наблюдения
Попробуйте сами. Добавьте nullable-поле comment VARCHAR(100) и выведите CHARACTER_MAXIMUM_LENGTH. Затем разработайте понятную ошибку импорта, если обязательного qty нет, вместо попытки угадать столбец по позиции.
Различить выбранную базу и список доступных таблиц
Старый код вызывает mysql_db_name и думает, что это имя выбранной базы. На самом деле он читает строку списка баз. Покажем выбранную схему отдельно, а её учебные таблицы получим явно ограниченным запросом.
Исходные данные
Две созданные таблицы
| Имя | Поле |
|---|---|
| mysql108_meta_listing_a | id INT PRIMARY KEY |
| mysql108_meta_listing_b | id INT PRIMARY KEY |
Что получится
Проверка контекста
| Вопрос | Ответ |
|---|---|
| DATABASE() совпадает с настройкой | да |
| Выбранная схема видна в каталоге | да |
Только две таблицы этого примера
| TABLE_NAME |
|---|
| mysql108_meta_listing_a |
| mysql108_meta_listing_b |
Малый фрагмент: сначала смысл действия
SELECT DATABASE();
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME IN ('mysql108_meta_listing_a','mysql108_meta_listing_b')
ORDER BY TABLE_NAME;Это фрагмент внутри показанного сценария: $db — уже установленное соединение; $result — результат соответствующего SELECT. Полный запуск ниже самостоятельно создаёт нужные входные таблицы. Если показан SQL, его выполняет query/execute_query из полной программы.
DATABASE() отвечает на вопрос о текущем контексте конкретного соединения; вне выбранной схемы результат может быть NULL. SCHEMATA содержит доступные сведения о схемах. TABLES описывает таблицы и представления; TABLE_SCHEMA и TABLE_NAME — разные колонки. В примере оба имени таблиц передаются параметрами условия IN, а результат сортируется по имени. Имена базы и таблиц не интерпретируются как номера строк каталога.
SHOW DATABASES и каталог показывают только то, что разрешено видеть текущему аккаунту. Отсутствие имени в списке не доказывает, что схемы физически нет. Для списка конкретного приложения обычно достаточно одной выделенной схемы и фильтра по нужным объектам. mysql_tablename извлекал имя из строки старого списка, а mysql_field_table — происхождение выходного столбца SELECT: это принципиально разные операции.
Ошибки и ограничения
Не публикуйте полный каталог сервера на диагностической странице сайта. Не принимайте первый результат SHOW DATABASES за текущую базу. Одинаковые имена таблиц встречаются в разных схемах; фильтр только по TABLE_NAME недостаточен.
Полная самостоятельная программа PHP 8 и входные файлы
<?php
declare(strict_types=1);
require __DIR__.'/mysql108-metadata-helper.php';
$db=legacy108Connect();$other=null;$created=[];$blocks=[];$checks=[];$observations=[];
try {
legacy108Create($db,$created,'mysql108_meta_listing_a','id INT PRIMARY KEY');
legacy108Create($db,$created,'mysql108_meta_listing_b','id INT PRIMARY KEY');
$current=legacy108Read($db,'SELECT DATABASE()')[0][0];
$visible=legacy108Read($db,'SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME=DATABASE()');
$tables=legacy108Read($db,'SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME IN (?,?) ORDER BY TABLE_NAME',['mysql108_meta_listing_a','mysql108_meta_listing_b']);
$same=$current===getenv('PHPMAN_MYSQL_DATABASE');$available=count($visible)===1&&$visible[0][0]===$current;
$blocks=[legacy108Block('Проверка контекста',['Вопрос','Ответ'],[['DATABASE() совпадает с настройкой',legacy108Yes($same)],['Выбранная схема видна в каталоге',legacy108Yes($available)]]),legacy108Block('Только две таблицы этого примера',['TABLE_NAME'],$tables)];
$checks=['selected_schema'=>$same,'visible_schema'=>$available,'owned_only'=>$tables===[['mysql108_meta_listing_a'],['mysql108_meta_listing_b']]];
$observations=[['Фактическое имя выбранной учебной базы',$current]];
legacy108Report('mysql108-meta-listing',$blocks,$checks,$observations,$db,[]);
} finally {legacy108Cleanup($db,$other,$created);}
echo "mysql108-meta-listing: saved result.html and result.json\n";
Ожидаемый результат
mysql108-meta-listing: saved result.html and result.json
Код использует mysqli, создаёт показанные учебные данные и сохраняет реальные result.html/result.json/observations.json. Уведомление консоли сообщает только о сохранении; полезный результат — таблицы выше и фактический HTML-файл. Helper и README включены в архив.
Скачать таблицы JSON · Открыть фактический результат · Скачать реальные наблюдения
Попробуйте сами. Измените SQL списка так, чтобы он возвращал только mysql108_meta_listing_b. Проверьте, что DATABASE() не поменялся: фильтрация списка не выбирает другую схему.
Практический вопрос: How to determine which MySQL database has been selected?. Путаются выбранная база, перечень доступных схем и сведения о хосте. Программа проверяет DATABASE() отдельно от каталога. Обсуждение задаёт ситуацию; семантика сверена с PHP/MySQL, программа и её учебные данные написаны отдельно.
Исторические функции: отдельные контракты и путь переноса
Каждая карточка отдельно разбирает параметры, возврат, ограничения, исторический контекст и два случая современного применения. Исторический фрагмент не запускается; запускаемые программы главы используют mysqli.
| Функция | Задача | Версия устаревания |
|---|---|---|
mysql_fetch_field | Прочитать описание одного выходного столбца отчёта | PHP5.5.0 → удаление7.0 |
mysql_field_flags | Узнать свойства колонки, по которым старый редактор строил форму | PHP5.5.0 → удаление7.0 |
mysql_field_len | Получить объявленную длину поля, не длину текущего товара | PHP5.5.0 → удаление7.0 |
mysql_field_name | Восстановить заголовок выбранной колонки старого отчёта | PHP5.5.0 → удаление7.0 |
mysql_field_seek | Выбрать, описание какого поля будет прочитано следующим | PHP5.5.0 → удаление7.0 |
mysql_field_table | Узнать, с какой таблицей связан столбец результата JOIN | PHP5.5.0 → удаление7.0 |
mysql_field_type | Разобраться со старым переключателем типа поля | PHP5.5.0 → удаление7.0 |
mysql_list_fields | Получить старый указатель описания столбцов таблицы | PHP5.4.0 → удаление7.0 |
mysql_list_tables | Перенести старый список объектов одной базы | PHP4.3.0 → удаление7.0 |
mysql_tablename | Прочитать имя таблицы из строки старого списка | PHP5.5.0 → удаление7.0 |
mysql_db_name | Прочитать имя базы из результата mysql_list_dbs | PHP5.5.0 → удаление7.0 |
mysql_list_dbs | Перечислить доступные базы старого сервера | PHP5.5.0 → удаление7.0 |
Следующий шаг: перенести реальный отчёт
Возьмите небольшой старый отчёт и запишите отдельно его заголовки, исходные поля и ожидаемые строки. Замените получение metadata, сохранив эти три договора. Затем проверьте чтение строк и буферизацию и диагностику конкретного подключения. Не переносите динамический SELECT* и редактирование неизвестных полей только потому, что старый код так работал.
Функции и методы этой темы
Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.
mysql_fetch_fieldПрочитать описание одного выходного столбца отчёта
PHP 4/5; deprecated 5.5.0; removed PHP 7.0 · mysql (removed)
mysql_fetch_field(resource $result, int $field_offset = 0): objectПрочитать описание одного выходного столбца отчёта.
| Параметр | Историческое значение и смысл |
|---|---|
| result | Открытый resource результата старого mysql_query; не SQL-строка, не массив и не объект mysqli_result. Для специальных списков источник указан отдельно. |
| field_offset = 0 | Номер поля начинается с нуля. В показанной исторической сигнатуре default=0, но пропущенный аргумент означает чтение следующего ещё не полученного описания через внутренний указатель; явно переданный 0 обращается к первому полю. |
Возврат и отказ. Объект описания поля. Его свойства: name — выходное имя; table — таблица или её alias; max_length — максимальная длина; not_null, primary_key, unique_key, multiple_key — признаки обязательности и ключей; numeric, blob — признаки числового/BLOB-поля; type — старое текстовое имя типа; unsigned и zerofill — дополнительные признаки. Историческая страница формально описывает успешный объект; её пример отдельно проверяет отсутствие метаданных.
Границы и исторические примечания. Имена чувствительны к регистру; при AS возвращалось имя alias, а не обязательно физическое имя. Это описание SELECT, а не универсальная схема таблицы. Старые max_length и type нельзя копировать в современные сравнения без пересмотра.
<?php
// Исторический контекст PHP 4/5. НЕ выполнять в PHP 7/8.
$meta = mysql_fetch_field($result, 0);
echo $meta->name;
Это фрагмент для узнавания старого кода, не самостоятельная программа и не проверка выполнения mysql_*. Переменные $link/$result/$list обозначают прежние ресурсы, созданные окружающим кодом. Современные запускаемые программы указаны в двух случаях переноса ниже.
Современный путь. mysqli_result::fetch_field() или fetch_fields(); прямой индекс — fetch_field_direct(). Современные orgname/orgtable сохраняют происхождение обычного поля, flags заменяет набор старых булевых свойств, type становится MYSQLI_TYPE_*. В PHP 8.1+ max_length всегда 0. PDOStatement::getColumnMeta — отдельный зависящий от драйвера контракт, а не одинаковый объект.
Два случая переноса и видимый результат
Заголовки CSV после AS. Показываем product_name пользователю, а name оставляем для объяснения происхождения колонки. Открыть исходные данные, результат и полную современную программу.
Последовательный генератор заголовков. Обходим описания полей отдельно от товарных строк и видим завершение курсора. Открыть исходные данные, результат и полную современную программу.
Общий маршрут переноса: подключение, кодировка и выбор API; запросы, ошибки и строки результата. Современные операции mysqli имеют отдельные карточки справочника.
mysql_field_flagsУзнать свойства колонки, по которым старый редактор строил форму
PHP 4/5; deprecated 5.5.0; removed PHP 7.0 · mysql (removed)
mysql_field_flags(resource $result, int $field_offset): string|falseУзнать свойства колонки, по которым старый редактор строил форму.
| Параметр | Историческое значение и смысл |
|---|---|
| result | Открытый resource результата старого mysql_query; не SQL-строка, не массив и не объект mysqli_result. Для специальных списков источник указан отдельно. |
| field_offset | Индекс выходного столбца от 0 до mysql_num_fields(result)-1. Несуществующий индекс вызывает E_WARNING; это индекс поля, не строки. |
Возврат и отказ. Строка слов, разделённых одним пробелом, либо false при отказе. Возможные слова: not_null, primary_key, unique_key, multiple_key, blob, unsigned, zerofill, binary, enum, auto_increment, timestamp; набор зависел от версии MySQL.
Границы и исторические примечания. Старый alias mysql_fieldflags также устарел. Проверка слов описывала свойства поля, но не правила пользователя и не полный состав составного индекса.
<?php
// Исторический контекст PHP 4/5. НЕ выполнять в PHP 7/8.
$words = mysql_field_flags($result, 0);
if ($words !== false) { $flags = explode(" ", $words); }
Это фрагмент для узнавания старого кода, не самостоятельная программа и не проверка выполнения mysql_*. Переменные $link/$result/$list обозначают прежние ресурсы, созданные окружающим кодом. Современные запускаемые программы указаны в двух случаях переноса ниже.
Современный путь. В mysqli fetch_field_direct(index)->flags возвращает битовую маску. Проверяйте ($flags & MYSQLI_NOT_NULL_FLAG) !== 0 и другие нужные именованные биты. Нельзя передать число в старый explode или сравнить всю маску с одним битом.
Два случая переноса и видимый результат
Отключить редактирование AUTO_INCREMENT. Проверяем отдельные признаки id и не ошибаемся при сочетании PRIMARY KEY с UNSIGNED. Открыть исходные данные, результат и полную современную программу.
Проверить вход импортёра. Сравниваем обязательность полей с явной схемой; краткая маска не заменяет полный каталог ограничений. Открыть исходные данные, результат и полную современную программу.
Общий маршрут переноса: подключение, кодировка и выбор API; запросы, ошибки и строки результата. Современные операции mysqli имеют отдельные карточки справочника.
mysql_field_lenПолучить объявленную длину поля, не длину текущего товара
PHP 4/5; deprecated 5.5.0; removed PHP 7.0 · mysql (removed)
mysql_field_len(resource $result, int $field_offset): int|falseПолучить объявленную длину поля, не длину текущего товара.
| Параметр | Историческое значение и смысл |
|---|---|
| result | Открытый resource результата старого mysql_query; не SQL-строка, не массив и не объект mysqli_result. Для специальных списков источник указан отдельно. |
| field_offset | Индекс выходного столбца от 0 до mysql_num_fields(result)-1. Несуществующий индекс вызывает E_WARNING; это индекс поля, не строки. |
Возврат и отказ. Целая длина поля по заданному индексу или false при отказе. Официальный пример связывает её с определением поля в схеме. Для длины значений конкретной строки служила другая функция — mysql_fetch_lengths.
Границы и исторические примечания. Старый alias mysql_fieldlen. Название length не даёт права считать число пользовательскими символами или автоматически ставить его в HTML maxlength. Единицы и кодировка важны при миграции.
<?php
// Исторический контекст PHP 4/5. НЕ выполнять в PHP 7/8.
$declared = mysql_field_len($result, 0);
// Это не strlen значения из текущей строки.
Это фрагмент для узнавания старого кода, не самостоятельная программа и не проверка выполнения mysql_*. Переменные $link/$result/$list обозначают прежние ресурсы, созданные окружающим кодом. Современные запускаемые программы указаны в двух случаях переноса ниже.
Современный путь. fetch_field_direct(index)->length описывает байтовую ширину результата. Для VARCHAR(n) используйте INFORMATION_SCHEMA.COLUMNS с CHARACTER_MAXIMUM_LENGTH и CHARACTER_OCTET_LENGTH. Для текущей строки — fetch_lengths/lengths; для подсчёта символов выбранного значения — CHAR_LENGTH в MySQL.
Два случая переноса и видимый результат
Подсказка допустимой длины формы. VARCHAR(12) и metadata length=48 не означают одинаковое количество символов. Открыть исходные данные, результат и полную современную программу.
Проверка договора CSV до чтения строк. Схему получаем даже из пустой таблицы; заполненность таблицы не меняет её определение. Открыть исходные данные, результат и полную современную программу.
Общий маршрут переноса: подключение, кодировка и выбор API; запросы, ошибки и строки результата. Современные операции mysqli имеют отдельные карточки справочника.
mysql_field_nameВосстановить заголовок выбранной колонки старого отчёта
PHP 4/5; deprecated 5.5.0; removed PHP 7.0 · mysql (removed)
mysql_field_name(resource $result, int $field_offset): string|falseВосстановить заголовок выбранной колонки старого отчёта.
| Параметр | Историческое значение и смысл |
|---|---|
| result | Открытый resource результата старого mysql_query; не SQL-строка, не массив и не объект mysqli_result. Для специальных списков источник указан отдельно. |
| field_offset | Индекс выходного столбца от 0 до mysql_num_fields(result)-1. Несуществующий индекс вызывает E_WARNING; это индекс поля, не строки. |
Возврат и отказ. Имя выходного поля по индексу или false при отказе. Имя чувствительно к регистру.
Границы и исторические примечания. Старый alias mysql_fieldname. Номер относится к SELECT-списку: изменение порядка запроса меняет соответствие индексов. AS задаёт имя результата; это не гарантированное исходное имя в схеме.
<?php
// Исторический контекст PHP 4/5. НЕ выполнять в PHP 7/8.
$heading = mysql_field_name($result, 0);
echo $heading;
Это фрагмент для узнавания старого кода, не самостоятельная программа и не проверка выполнения mysql_*. Переменные $link/$result/$list обозначают прежние ресурсы, созданные окружающим кодом. Современные запускаемые программы указаны в двух случаях переноса ниже.
Современный путь. fetch_field_direct(index)->name; если необходимо происхождение обычного поля, отдельно orgname. Для всей строки имён удобен fetch_fields. Динамическое построение SQL по именам отчёта должно иметь разрешённый список, а не доверять пришедшему из браузера заголовку.
Два случая переноса и видимый результат
Показать понятный заголовок выгрузки. Выходное product_name отделено от исходного name. Открыть исходные данные, результат и полную современную программу.
Обновить старый индексный генератор. Изменение SELECT title,id,sku заставляет пересмотреть номер, а обход fetch_fields делает порядок явным. Открыть исходные данные, результат и полную современную программу.
Общий маршрут переноса: подключение, кодировка и выбор API; запросы, ошибки и строки результата. Современные операции mysqli имеют отдельные карточки справочника.
mysql_field_seekВыбрать, описание какого поля будет прочитано следующим
PHP 4/5; deprecated 5.5.0; removed PHP 7.0 · mysql (removed)
mysql_field_seek(resource $result, int $field_offset): boolВыбрать, описание какого поля будет прочитано следующим.
| Параметр | Историческое значение и смысл |
|---|---|
| result | Открытый resource результата старого mysql_query; не SQL-строка, не массив и не объект mysqli_result. Для специальных списков источник указан отдельно. |
| field_offset | Индекс выходного столбца от 0 до mysql_num_fields(result)-1. Несуществующий индекс вызывает E_WARNING; это индекс поля, не строки. |
Возврат и отказ. true при успешном перемещении, false при отказе. Следующий mysql_fetch_field без явно заданного offset читает поле с установленного места.
Границы и исторические примечания. Это указатель описаний столбцов; mysql_data_seek работает с товарными строками. Перемещение не выполняет новый SQL и не меняет таблицу. Неиспользуемый или освобождённый resource не является допустимым результатом.
<?php
// Исторический контекст PHP 4/5. НЕ выполнять в PHP 7/8.
if (mysql_field_seek($result, 2)) {
$meta = mysql_fetch_field($result);
}
Это фрагмент для узнавания старого кода, не самостоятельная программа и не проверка выполнения mysql_*. Переменные $link/$result/$list обозначают прежние ресурсы, созданные окружающим кодом. Современные запускаемые программы указаны в двух случаях переноса ниже.
Современный путь. mysqli_result::field_seek(index), затем fetch_field(). Для одноразового чтения лучше fetch_field_direct(index), для всех описаний — fetch_fields(). PDO row-cursor нельзя объявлять эквивалентом курсора метаданных: это другой уровень данных.
Два случая переноса и видимый результат
Перейти к третьему заголовку. Индекс2 выбирает title, но первая строка данных ещё не прочитана. Открыть исходные данные, результат и полную современную программу.
Обойти поля для подписи отчёта. Массив fetch_fields позволяет получить все заголовки и происхождение без ручного переставления указателя. Открыть исходные данные, результат и полную современную программу.
Общий маршрут переноса: подключение, кодировка и выбор API; запросы, ошибки и строки результата. Современные операции mysqli имеют отдельные карточки справочника.
mysql_field_tableУзнать, с какой таблицей связан столбец результата JOIN
PHP 4/5; deprecated 5.5.0; removed PHP 7.0 · mysql (removed)
mysql_field_table(resource $result, int $field_offset): stringУзнать, с какой таблицей связан столбец результата JOIN.
| Параметр | Историческое значение и смысл |
|---|---|
| result | Открытый resource результата старого mysql_query; не SQL-строка, не массив и не объект mysqli_result. Для специальных списков источник указан отдельно. |
| field_offset | Индекс выходного столбца от 0 до mysql_num_fields(result)-1. Несуществующий индекс вызывает E_WARNING; это индекс поля, не строки. |
Возврат и отказ. Имя таблицы успешного выходного поля. Официальная историческая сигнатура объявляет string; неверный индекс описан через E_WARNING, не следует придумывать для всех случаев универсальный false-контракт.
Границы и исторические примечания. Старый alias mysql_fieldtable. Речь о происхождении колонки, не о получении списка таблиц. Alias таблицы и вычисляемое выражение требуют отдельного понимания; не все результаты SELECT принадлежат одному физическому полю.
<?php
// Исторический контекст PHP 4/5. НЕ выполнять в PHP 7/8.
$table = mysql_field_table($result, 0);
$field = mysql_field_name($result, 0);
Это фрагмент для узнавания старого кода, не самостоятельная программа и не проверка выполнения mysql_*. Переменные $link/$result/$list обозначают прежние ресурсы, созданные окружающим кодом. Современные запускаемые программы указаны в двух случаях переноса ниже.
Современный путь. fetch_field_direct(index)->table и orgtable. Первое может содержать alias, второе — исходную таблицу; для выражения сведения о таблице могут быть пустыми. Для списка объектов схемы используйте INFORMATION_SCHEMA.TABLES или SHOW TABLES.
Два случая переноса и видимый результат
Указать происхождение столбца в JOIN-отчёте. table=p и orgtable=mysql108_meta_aliases отвечают на разные вопросы. Открыть исходные данные, результат и полную современную программу.
Отделить происхождение от каталога. Список двух таблиц приложения получается отдельным SQL, без осмотра случайного SELECT. Открыть исходные данные, результат и полную современную программу.
Общий маршрут переноса: подключение, кодировка и выбор API; запросы, ошибки и строки результата. Современные операции mysqli имеют отдельные карточки справочника.
mysql_field_typeРазобраться со старым переключателем типа поля
PHP 4/5; deprecated 5.5.0; removed PHP 7.0 · mysql (removed)
mysql_field_type(resource $result, int $field_offset): stringРазобраться со старым переключателем типа поля.
| Параметр | Историческое значение и смысл |
|---|---|
| result | Открытый resource результата старого mysql_query; не SQL-строка, не массив и не объект mysqli_result. Для специальных списков источник указан отдельно. |
| field_offset | Индекс выходного столбца от 0 до mysql_num_fields(result)-1. Несуществующий индекс вызывает E_WARNING; это индекс поля, не строки. |
Возврат и отказ. Текстовый тип, например int, real, string, blob и другие типы, описанные в MySQL. Историческая сигнатура string и предупреждение при неверном индексе не равны современной числовой маске типов.
Границы и исторические примечания. Старый alias mysql_fieldtype. Тип SQL-поля, формат бизнес-значения и тип PHP-значения после fetch различаются. DECIMAL для цены не следует превращать в float только потому, что старый код искал слово real.
<?php
// Исторический контекст PHP 4/5. НЕ выполнять в PHP 7/8.
$kind = mysql_field_type($result, 0);
// Старое сравнение $kind === "int" относится к ext/mysql.
Это фрагмент для узнавания старого кода, не самостоятельная программа и не проверка выполнения mysql_*. Переменные $link/$result/$list обозначают прежние ресурсы, созданные окружающим кодом. Современные запускаемые программы указаны в двух случаях переноса ниже.
Современный путь. mysqli metadata ->type содержит числовой MYSQLI_TYPE_*; сопоставляйте нужные константы, а не строки старого API. Для полного определения столбца TABLE используйте DATA_TYPE/COLUMN_TYPE в INFORMATION_SCHEMA. PDO getColumnMeta имеет другой набор ключей и поддержку драйвера.
Два случая переноса и видимый результат
Перенос форматирования цены. Сохраняем десятичную строку 250.00 и отдельно читаем фактический код SQL-типа. Открыть исходные данные, результат и полную современную программу.
Проверить схему загрузки. DATA_TYPE явно показывает int/varchar независимо от того, есть ли в таблице строки. Открыть исходные данные, результат и полную современную программу.
Общий маршрут переноса: подключение, кодировка и выбор API; запросы, ошибки и строки результата. Современные операции mysqli имеют отдельные карточки справочника.
mysql_list_fieldsПолучить старый указатель описания столбцов таблицы
PHP 4/5; deprecated 5.4.0; removed PHP 7.0 · mysql (removed)
mysql_list_fields(string $database_name, string $table_name, resource $link_identifier = NULL): resourceПолучить старый указатель описания столбцов таблицы.
| Параметр | Историческое значение и смысл |
|---|---|
| database_name | Имя базы, в которой находится таблица. |
| table_name | Имя таблицы, описание которой нужно получить. |
| link_identifier = NULL | Resource старого подключения. При пропуске выбиралось последнее соединение mysql_connect; если его не было, делалась попытка mysql_connect без аргументов. Неудача установить соединение давала E_WARNING. В новом коде передавайте конкретный объект mysqli. |
Возврат и отказ. Resource указателя описаний при успехе, false при отказе. Его передавали mysql_field_flags, mysql_field_len, mysql_field_name, mysql_field_type. Это не массив строк товаров.
Границы и исторические примечания. Функция отдельно deprecated уже с PHP 5.4.0; alias mysql_listfields. Ещё старая документация советовала SQL SHOW COLUMNS FROM table [LIKE pattern]. SHOW COLUMNS возвращает обычные строки-описания и требует другого чтения, чем старый специальный указатель.
<?php
// Исторический контекст PHP 4/5. НЕ выполнять в PHP 7/8.
$fields = mysql_list_fields("shop", "products", $link);
// Старый специальный resource метаданных.
Это фрагмент для узнавания старого кода, не самостоятельная программа и не проверка выполнения mysql_*. Переменные $link/$result/$list обозначают прежние ресурсы, созданные окружающим кодом. Современные запускаемые программы указаны в двух случаях переноса ниже.
Современный путь. SHOW COLUMNS либо INFORMATION_SCHEMA.COLUMNS через mysqli/PDO. При переносе меняются не только имя вызова, но и форма результата: Field/Type/Null/Key/Default/Extra — данные строк каталога. Подстановка имён SQL-таблиц и параметров значений имеет разные правила.
Два случая переноса и видимый результат
Проверить пустую таблицу перед импортом. Ноль товаров не мешает получить все три определения колонок. Открыть исходные данные, результат и полную современную программу.
Получить лимиты текста для договора. INFORMATION_SCHEMA различает число символов и максимальный объём байтов. Открыть исходные данные, результат и полную современную программу.
Общий маршрут переноса: подключение, кодировка и выбор API; запросы, ошибки и строки результата. Современные операции mysqli имеют отдельные карточки справочника.
mysql_list_tablesПеренести старый список объектов одной базы
PHP 4/5; deprecated 4.3.0; removed PHP 7.0 · mysql (removed)
mysql_list_tables(string $database, resource $link_identifier = NULL): resource|falseПеренести старый список объектов одной базы.
| Параметр | Историческое значение и смысл |
|---|---|
| database | Имя базы, таблицы которой перечисляются. |
| link_identifier = NULL | Resource старого подключения. При пропуске выбиралось последнее соединение mysql_connect; если его не было, делалась попытка mysql_connect без аргументов. Неудача установить соединение давала E_WARNING. В новом коде передавайте конкретный объект mysqli. |
Возврат и отказ. Resource результата со списком при успехе либо false при отказе. Его читали mysql_tablename по номеру строки или обычными fetch-функциями старого API.
Границы и исторические примечания. Deprecated с PHP 4.3.0, alias mysql_listtables. Рекомендованная уже тогда SQL-форма — SHOW TABLES [FROM db_name] [LIKE pattern]. Список зависит от прав и не означает, что текущая выбранная база поменялась.
<?php
// Исторический контекст PHP 4/5. НЕ выполнять в PHP 7/8.
$list = mysql_list_tables("shop", $link);
// Чтение строк: mysql_tablename($list, $row).
Это фрагмент для узнавания старого кода, не самостоятельная программа и не проверка выполнения mysql_*. Переменные $link/$result/$list обозначают прежние ресурсы, созданные окружающим кодом. Современные запускаемые программы указаны в двух случаях переноса ниже.
Современный путь. SHOW TABLES через mysqli/PDO либо INFORMATION_SCHEMA.TABLES с явным TABLE_SCHEMA. Если нужны только собственные объекты, задавайте фильтр; полная структура сервера не обязательна пользователю приложения.
Два случая переноса и видимый результат
Показать только таблицы модуля. Два разрешённых имени возвращаются в заданном ORDER BY. Открыть исходные данные, результат и полную современную программу.
После выбора таблицы проверить её схему. Список имён и список столбцов — два разных запроса и два отдельных договора. Открыть исходные данные, результат и полную современную программу.
Общий маршрут переноса: подключение, кодировка и выбор API; запросы, ошибки и строки результата. Современные операции mysqli имеют отдельные карточки справочника.
mysql_tablenameПрочитать имя таблицы из строки старого списка
PHP 4/5; deprecated 5.5.0; removed PHP 7.0 · mysql (removed)
mysql_tablename(resource $result, int $i): string|falseПрочитать имя таблицы из строки старого списка.
| Параметр | Историческое значение и смысл |
|---|---|
| result | Resource, полученный mysql_list_tables; не результат произвольного SELECT товаров. |
| i | Целый номер строки/таблицы списка, начиная с0. Количество строк узнавалось mysql_num_rows. |
Возврат и отказ. Имя таблицы по номеру строки либо false при отказе. Вместо неё список можно было читать обычным mysql_fetch_array.
Границы и исторические примечания. Название часто путают с mysql_field_table, но здесь выбирается строка списка таблиц. Позиция не является постоянным идентификатором объекта; порядок списка может изменяться.
<?php
// Исторический контекст PHP 4/5. НЕ выполнять в PHP 7/8.
$name = mysql_tablename($list, 0);
// Первая строка списка таблиц, не первое поле SELECT.
Это фрагмент для узнавания старого кода, не самостоятельная программа и не проверка выполнения mysql_*. Переменные $link/$result/$list обозначают прежние ресурсы, созданные окружающим кодом. Современные запускаемые программы указаны в двух случаях переноса ниже.
Современный путь. Получите SHOW TABLES и читайте fetch_row()[0] в цикле либо выберите TABLE_NAME из INFORMATION_SCHEMA.TABLES. Для точного имени используйте условие, а не случайный номер строки.
Два случая переноса и видимый результат
Выдать список таблиц интерфейсу. Читаем имена строками и сортируем явно. Открыть исходные данные, результат и полную современную программу.
Проверить выбранный объект. Передаём разрешённое имя в параметр запроса к каталогу столбцов, не считаем имя номером поля. Открыть исходные данные, результат и полную современную программу.
Общий маршрут переноса: подключение, кодировка и выбор API; запросы, ошибки и строки результата. Современные операции mysqli имеют отдельные карточки справочника.
mysql_db_nameПрочитать имя базы из результата mysql_list_dbs
PHP 4/5; deprecated 5.5.0; removed PHP 7.0 · mysql (removed)
mysql_db_name(resource $result, int $row, mixed $field = NULL): stringПрочитать имя базы из результата mysql_list_dbs.
| Параметр | Историческое значение и смысл |
|---|---|
| result | Resource результата mysql_list_dbs. |
| row | Индекс строки списка баз, начиная с0. |
| field = NULL | Имя поля результата; необязательный третий аргумент исторического API. |
Возврат и отказ. Имя базы при успехе, false при отказе (это дополнительно указано в тексте Return Values, хотя историческая сигнатура показывает string). Для причины отказа предлагался mysql_error.
Границы и исторические примечания. Alias mysql_dbname. Функция не отвечала «какая база выбрана сейчас»: она извлекала строку списка. Предложение SELECT DATABASE() на официальной странице относится только к задаче текущей схемы, не ко всему перечислению.
<?php
// Исторический контекст PHP 4/5. НЕ выполнять в PHP 7/8.
$name = mysql_db_name($databaseList, 0);
// Это первый элемент списка, а не обязательно текущая база.
Это фрагмент для узнавания старого кода, не самостоятельная программа и не проверка выполнения mysql_*. Переменные $link/$result/$list обозначают прежние ресурсы, созданные окружающим кодом. Современные запускаемые программы указаны в двух случаях переноса ниже.
Современный путь. Текущая схема: SELECT DATABASE(). Список видимых схем: SHOW DATABASES или INFORMATION_SCHEMA.SCHEMATA, затем обычное чтение строк. При отсутствии выбранной схемы DATABASE() может вернуть NULL.
Два случая переноса и видимый результат
Устранить ошибку выбора базы в старой админке. Сравниваем DATABASE() с настройкой отдельно от видимости схемы. Открыть исходные данные, результат и полную современную программу.
Проверить контекст перед административным планом. Показываем выбранную схему, но не подменяем этим проверку прав CREATE/DROP DATABASE. Открыть исходные данные, результат и полную современную программу.
Общий маршрут переноса: подключение, кодировка и выбор API; запросы, ошибки и строки результата. Современные операции mysqli имеют отдельные карточки справочника.
mysql_list_dbsПеречислить доступные базы старого сервера
PHP 4/5; deprecated 5.5.0; removed PHP 7.0 · mysql (removed)
mysql_list_dbs(resource $link_identifier = NULL): resourceПеречислить доступные базы старого сервера.
| Параметр | Историческое значение и смысл |
|---|---|
| link_identifier = NULL | Resource старого подключения. При пропуске выбиралось последнее соединение mysql_connect; если его не было, делалась попытка mysql_connect без аргументов. Неудача установить соединение давала E_WARNING. В новом коде передавайте конкретный объект mysqli. |
Возврат и отказ. Resource результата при успехе, false при отказе. Официальная сигнатура resource не перечисляет false, но текст возврата его оговаривает. Результат читался как таблица, в частности через mysql_db_name или обычные fetch-функции.
Границы и исторические примечания. Alias mysql_listdbs. Доступность списка зависит от аккаунта и прав; нельзя считать его полным инвентарём физического сервера. mysql_select_db выбирала контекст, а list_dbs только перечисляла.
<?php
// Исторический контекст PHP 4/5. НЕ выполнять в PHP 7/8.
$list = mysql_list_dbs($link);
if ($list !== false) { $firstName = mysql_db_name($list, 0); }
Это фрагмент для узнавания старого кода, не самостоятельная программа и не проверка выполнения mysql_*. Переменные $link/$result/$list обозначают прежние ресурсы, созданные окружающим кодом. Современные запускаемые программы указаны в двух случаях переноса ниже.
Современный путь. SHOW DATABASES либо запрос к INFORMATION_SCHEMA.SCHEMATA. Для задачи «где я сейчас» достаточно DATABASE(), а для приложения обычно не требуется список чужих схем.
Два случая переноса и видимый результат
Проверить видимость собственной схемы. Фильтр SCHEMA_NAME=DATABASE() не открывает весь каталог пользователю. Открыть исходные данные, результат и полную современную программу.
Отделить наличие схемы от права удалить её. Чтение каталога и административный DDL требуют разных решений. Открыть исходные данные, результат и полную современную программу.
Общий маршрут переноса: подключение, кодировка и выбор API; запросы, ошибки и строки результата. Современные операции mysqli имеют отдельные карточки справочника.
Код и руководство с собой
Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.
Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.
Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.


