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

Дерево руководства
Глава 74 · После основных запросов Firebird
Firebird: fbird_* в существующем коде — каталог, параметры и формы строк
Поддержка существующего native-кода: экран остатков, повторный фильтр, массив/строка/объект и правильный порядок полей импорта.
Как читать существующий код с fbird_*
В работающем проекте встретились fbird_connect, fbird_query и fbird_fetch_assoc. Переписывать всё приложение для чтения двух товаров не требуется: сначала разберитесь, какие ресурсы проходят между этими вызовами. Здесь вы получите экран наличия, две вкладки остатков, три понятные формы строки и импорт с объяснимым отказом неполной записи.
- fbird_connect = ibase_connect → соединение
- query или prepare → execute → результат SELECT
- fetch_assoc / fetch_row / fetch_object → значения PHP
- free_result → результат больше не нужен
- free_query → подготовленная команда больше не нужна
Alias — второе имя той же функции. Представьте две подписи у одной кнопки: они запускают один обработчик, а не два разных хранилища. В исходнике выбранного драйвера это PHP_FALIAS. Такое имя само не ускоряет SQL, не меняет транзакции, не превращает native interbase в PDO и не устраняет несовместимость старой базы с другим SQL-диалектом.
Перед главой достаточно понять соединение и SELECT, подготовленную команду и массивы и объекты результата. У каждого раздела сначала короткая запись, затем полный самостоятельный файл с собственными данными. Проверяемое окружение — PHP 8.2.35, расширение interbase 3.0.1, Firebird 5.0.4; исторические отметки PHP 5 / PHP 7 < 7.4 относятся к прежней встроенной поставке, не к отсутствию этих имён в отдельном драйвере.
| Практическая задача | Раздел |
|---|---|
| Экран наличия: получить только два подходящих товара | Открыть сценарий |
| Две вкладки остатков одним подготовленным SELECT | Открыть сценарий |
| Одна карточка в массиве, строке CSV и объекте | Открыть сценарий |
| Импорт: связать имена полей с позициями INSERT | Открыть сценарий |
Подготовка примеров и служебные функции
ZIP содержит example.php, lab.php и README.txt. README объясняет отдельную локальную учебную базу и запуск CLI; файл создаёт только свою случайно названную таблицу, а в конце удаляет её. Соединение в example.php действительно открывает fbird_connect. Вспомогательные f161* готовят данные, сохраняют диагностику и результат; aliasRows161 вызывает выбранный fbird_fetch_* и отличает EOF от отказа. Все 13 разбираемых имён присутствуют в основных сценариях, а не только в списке функций.
Маленькие фрагменты ниже предполагают готовое соединение и показанную таблицу; это отдельные шаги полного файла. Ресурс — ссылка PHP на состояние драйвера, а не строка данных. Не печатайте его как результат бизнес-задачи. Данные можно прочитать в массив, закрыть ресурс и затем сформировать HTML. В HTML-результате текст экранируется; в JSON сохраняются строки, числа, null и условия проверки.
Экран наличия: получить только два подходящих товара
Вы поддерживаете складской экран старого сайта. Для него нужны две активные позиции с остатком, название и количество. Получим ровно эти поля и строки из Firebird: браузеру не потребуется отсеивать архив, сортировать большой PHP-массив или угадывать номера колонок.
- fbird_connect → соединение с учебной базой
- WHERE active=1 AND qty>=1 → только подходящие позиции
- ORDER BY id ROWS 2 → стабильные первые две строки
- num_fields/field_info → описание трёх колонок
- fetch_assoc → Кабель: 3; Клемма: 7
- free_result → копии данных остаются в PHP
Сначала один шаг
$result = fbird_query($db, 'SELECT title AS "title", qty AS "qty" FROM items WHERE qty>=? ORDER BY id ROWS 2', 1);
if ($result === false) { throw new RuntimeException("Каталог недоступен"); }
$row = fbird_fetch_assoc($result);
if ($row !== false) { echo $row["title"], ": ", $row["qty"]; }
fbird_free_result($result);Здесь $db — уже открытое соединение, items — существующая таблица. Знак ? обозначает значение фильтра, которое следующим аргументом передаётся отдельно от SQL. AS "title" задаёт точный ключ массива; двойные кавычки сохраняют регистр. Один fetch читает одну следующую строку, поэтому для всех карточек нужен цикл. Минимальный фрагмент показывает только первую; полный файл сохраняет обе строки и отдельно различает конец чтения и ошибку.
Что получится
| Наблюдение | Результат |
|---|---|
| Колонки экрана | id, title, qty |
| Товаров на экране | 2 |
| Первая карточка | Кабель: 3 |
| Вторая карточка | Клемма: 7 |
| Архивные и нулевые позиции исключены | да |
| Результат освобождён | да |
<?php
declare(strict_types=1);
require __DIR__.'/lab.php';
$db=null;$owned=$removed=$rows=$checks=$observations=[];
try {
$config=f161Config();$connect=f161Capture(static fn()=>fbird_connect(
$config['database'],$config['user'],$config['password'],'UTF8',0,3));
if (!is_resource($connect['value']) || $connect['warning']) {f161Failure('Соединение не открыто',$connect);}
$db=$connect['value'];unset($connect);$runtime=f161Runtime($db,$config);
function aliasResult161($value,string $operation) {
if (!is_resource($value)) {throw new RuntimeException($operation.': ожидался результат SELECT.');}
return $value;
}
function aliasFreeResult161(&$result): bool {
$call=f161Capture(static fn()=>fbird_free_result($result));$result=null;
if ($call['value']!==true || $call['warning']) {f161Failure('Результат не освобождён',$call);}
return true;
}
function aliasFreeQuery161(&$query): bool {
$call=f161Capture(static fn()=>fbird_free_query($query));$query=null;
if ($call['value']!==true || $call['warning']) {f161Failure('Команда не освобождена',$call);}
return true;
}
function aliasRows161($result,string $shape='assoc'): array {
$rows=[];
while (true) {
$call=f161Capture(static fn()=>match($shape) {
'assoc'=>fbird_fetch_assoc($result),
'row'=>fbird_fetch_row($result),
'object'=>fbird_fetch_object($result),
default=>throw new InvalidArgumentException('Неизвестная форма строки.')
});
if ($call['value']===false) {
if ($call['warning'] || $call['code']!==0) {f161Failure('Чтение прервано',$call);}
break;
}
$rows[]=$call['value'];
}
return $rows;
}
function aliasPrepare161($db,string $sql) {
$call=f161Capture(static fn()=>fbird_prepare($db,$sql));
if (!is_resource($call['value']) || $call['warning']) {f161Failure('Команда не подготовлена',$call);}
return $call['value'];
}
function aliasExecute161($query,array $values) {
$call=f161Capture(static fn()=>fbird_execute($query,...$values));
if ($call['value']===false || $call['warning']) {f161Failure('Команда не выполнена',$call);}
return $call['value'];
}
$name=f161OwnTable($db,$owned,'screen','(id INTEGER NOT NULL PRIMARY KEY,title VARCHAR(40) CHARACTER SET UTF8 NOT NULL,qty INTEGER NOT NULL,active SMALLINT NOT NULL)');
$q=f161Qualified($name);
foreach ([[1,'Кабель',3,1],[2,'Клемма',7,1],[3,'Архивная позиция',99,0],[4,'Лента',0,1]] as $item) {
f161Command($db,"INSERT INTO $q (id,title,qty,active) VALUES (?,?,?,?)",$item);
}
f161Commit($db);
$call=f161Capture(static fn()=>fbird_query($db,"SELECT id AS \"id\",title AS \"title\",qty AS \"qty\" FROM $q WHERE active=? AND qty>=? ORDER BY id ROWS 2",1,1));
if ($call['value']===false || $call['warning']) {f161Failure('Каталог не прочитан',$call);}
$result=aliasResult161($call['value'],'Каталог');unset($call);
try {
$columns=fbird_num_fields($result);$aliases=[];$metadata=[];
for ($i=0;$i<$columns;$i++) {
$info=fbird_field_info($result,$i);
if ($info===false) {throw new RuntimeException('Описание колонки отсутствует.');}
$aliases[]=$info['alias'];
$metadata[]=['alias'=>$info['alias'],'type'=>$info['type'],'length'=>$info['length']];
}
$items=aliasRows161($result);
} finally {$released=aliasFreeResult161($result);}
$rows=[['Колонки экрана',implode(', ',$aliases)],['Товаров на экране',count($items)],
['Первая карточка',$items[0]['title'].': '.$items[0]['qty']],['Вторая карточка',$items[1]['title'].': '.$items[1]['qty']],
['Архивные и нулевые позиции исключены',array_column($items,'id')===[1,2]],['Результат освобождён',$released]];
$checks=['screen_columns'=>$columns===3 && $aliases===['id','title','qty'],
'screen_rows'=>$items===[['id'=>1,'title'=>'Кабель','qty'=>3],['id'=>2,'title'=>'Клемма','qty'=>7]],
'first_row_preserved'=>$items[0]['id']===1,'result_released'=>$released && $result===null];
$observations=['selected'=>$items,'columns'=>$metadata,'filter'=>['active'=>1,'minimum_qty'=>1,'row_limit'=>2],
'sql_does_filter_order_and_limit'=>true,'connection_function'=>'fbird_connect'];
} finally {
if (is_resource($db)) {try {$removed=f161Cleanup($db,$owned);} finally {ibase_close($db);}}
}
f161Report('fb161-alias-catalog-screen','Экран наличия: получить только два подходящих товара',$rows,$checks,$observations,$runtime,$owned,$removed);
Ожидаемый результат
Колонки экрана — id, title, qty
Товаров на экране — 2
Первая карточка — Кабель: 3
Вторая карточка — Клемма: 7
Архивные и нулевые позиции исключены — да
Результат освобождён — да
Самостоятельный CLI-файл: одна своя таблица, реальные fbird_* вызовы, ограниченные выборки, result.html/result.json, освобождение ресурсов и удаление своей таблицы. lab.php и README.txt приложены.
Фактический HTML-результат · JSON со значениями и проверками.
Ошибки и границы
Метаданные не двигают курсор, а пробный fetch двигает. Не читайте первую строку «для проверки» и затем не начинайте второй цикл без неё. ROWS 2 ограничивает передачу, но само по себе не гарантирует быстрый план без подходящих индексов. Поля, фильтрация и сортировка нужны в SQL. Имя fbird_query не меняет диалект, кодировку и правила доступа; подмена его на ibase_query не исправит неправильный запрос.
В реальной задаче старой базы Firebird 2.5 запрос через PDO упирался в несоответствие SQL-диалекта соединения и базы. Исходная задача на Stack Overflow. Наш вывод: сначала установить драйвер, диалект и кодировку. Переименование fbird_* в ibase_* не переводит native API в PDO и не меняет диалект существующей базы. Учебная база создаётся с диалектом 3; перенос старой требует отдельного плана.
Попробуйте изменить задачу
Сделайте экран только для остатков от 5. Какая строка появится и сколько колонок вернёт num_fields?
Ожидаемое решение
Передайте minimum_qty=5. Вернётся Клемма: 7; архивная позиция останется исключённой. num_fields по-прежнему равен 3, потому что это число колонок, а не товаров.
Две вкладки остатков одним подготовленным SELECT
Дежурный открывает вкладку «в наличии», затем «малый остаток». Столбцы и условия запроса одинаковые, меняются только две границы количества. Подготовим шаблон один раз, выполним с двумя наборами значений и сохраним нулевой остаток как число 0.
- prepare SQL с BETWEEN ? AND ? → команда
- num_params=2; param_info=INTEGER/INTEGER
- execute(2,8) → Кабель, Клемма
- free_result первой вкладки
- execute(0,1) → Лента: 0
- free_result → free_query
Сначала один шаг
$query = fbird_prepare($db, "SELECT title,qty FROM items WHERE qty BETWEEN ? AND ? ORDER BY id");
if ($query === false) { throw new RuntimeException("Фильтр не подготовлен"); }
$result = fbird_execute($query, 2, 8);
// Прочитать и освободить result.
// Для другой вкладки выполнить тот же query с 0, 1.
// После последней вкладки освободить query.prepare возвращает команду, но ещё не строки. execute связывает значения в порядке ?: сначала минимум, потом максимум. Число входных мест не связано с числом колонок. Оба параметра INTEGER, поэтому метаданные не смогут узнать, что минимум и максимум перепутаны. Для числовой строки fetch_row позиция 0 — title, позиция 1 — qty, потому что именно так записан SELECT.
Что получится
| Наблюдение | Результат |
|---|---|
| Входных параметров | 2 |
| Типы границ | INTEGER / INTEGER |
| В наличии | Кабель, Клемма |
| Малый остаток | Лента: 0 |
| Подготовок / выполнений | 1 / 2 |
| Результатов освобождено | 2 |
| Команда освобождена | да |
<?php
declare(strict_types=1);
require __DIR__.'/lab.php';
$db=null;$owned=$removed=$rows=$checks=$observations=[];
try {
$config=f161Config();$connect=f161Capture(static fn()=>fbird_connect(
$config['database'],$config['user'],$config['password'],'UTF8',0,3));
if (!is_resource($connect['value']) || $connect['warning']) {f161Failure('Соединение не открыто',$connect);}
$db=$connect['value'];unset($connect);$runtime=f161Runtime($db,$config);
function aliasResult161($value,string $operation) {
if (!is_resource($value)) {throw new RuntimeException($operation.': ожидался результат SELECT.');}
return $value;
}
function aliasFreeResult161(&$result): bool {
$call=f161Capture(static fn()=>fbird_free_result($result));$result=null;
if ($call['value']!==true || $call['warning']) {f161Failure('Результат не освобождён',$call);}
return true;
}
function aliasFreeQuery161(&$query): bool {
$call=f161Capture(static fn()=>fbird_free_query($query));$query=null;
if ($call['value']!==true || $call['warning']) {f161Failure('Команда не освобождена',$call);}
return true;
}
function aliasRows161($result,string $shape='assoc'): array {
$rows=[];
while (true) {
$call=f161Capture(static fn()=>match($shape) {
'assoc'=>fbird_fetch_assoc($result),
'row'=>fbird_fetch_row($result),
'object'=>fbird_fetch_object($result),
default=>throw new InvalidArgumentException('Неизвестная форма строки.')
});
if ($call['value']===false) {
if ($call['warning'] || $call['code']!==0) {f161Failure('Чтение прервано',$call);}
break;
}
$rows[]=$call['value'];
}
return $rows;
}
function aliasPrepare161($db,string $sql) {
$call=f161Capture(static fn()=>fbird_prepare($db,$sql));
if (!is_resource($call['value']) || $call['warning']) {f161Failure('Команда не подготовлена',$call);}
return $call['value'];
}
function aliasExecute161($query,array $values) {
$call=f161Capture(static fn()=>fbird_execute($query,...$values));
if ($call['value']===false || $call['warning']) {f161Failure('Команда не выполнена',$call);}
return $call['value'];
}
$name=f161OwnTable($db,$owned,'filter','(id INTEGER NOT NULL PRIMARY KEY,title VARCHAR(40) CHARACTER SET UTF8 NOT NULL,qty INTEGER NOT NULL)');
$q=f161Qualified($name);
foreach ([[1,'Кабель',3],[2,'Клемма',7],[3,'Лента',0]] as $item) {f161Command($db,"INSERT INTO $q (id,title,qty) VALUES (?,?,?)",$item);}
f161Commit($db);
$query=aliasPrepare161($db,"SELECT title AS \"title\",qty AS \"qty\" FROM $q WHERE qty BETWEEN ? AND ? ORDER BY id ROWS 10");
try {
$count=fbird_num_params($query);$types=[];
for ($i=0;$i<$count;$i++) {
$info=fbird_param_info($query,$i);
if ($info===false) {throw new RuntimeException('Параметр не описан.');}
$types[]=$info['type'];
}
$tabs=[];$resultReleases=0;
foreach (['available'=>[2,8],'empty'=>[0,1]] as $tab=>$values) {
if (count($values)!==$count || $values[0]>$values[1]) {throw new DomainException('Неверные границы фильтра.');}
$result=aliasResult161(aliasExecute161($query,$values),'Вкладка');
try {$tabs[$tab]=aliasRows161($result,'row');}
finally {aliasFreeResult161($result);$resultReleases++;}
}
} finally {$released=aliasFreeQuery161($query);}
$rows=[['Входных параметров',$count],['Типы границ',implode(' / ',$types)],
['В наличии',implode(', ',array_column($tabs['available'],0))],['Малый остаток',$tabs['empty'][0][0].': '.$tabs['empty'][0][1]],
['Подготовок / выполнений','1 / 2'],['Результатов освобождено',$resultReleases],['Команда освобождена',$released]];
$checks=['parameter_contract'=>$count===2 && $types===['INTEGER','INTEGER'],
'available_rows'=>$tabs['available']===[['Кабель',3],['Клемма',7]],'zero_stock_preserved'=>$tabs['empty']===[['Лента',0]],
'results_released'=>$resultReleases===2,'query_released'=>$released && $query===null];
$observations=['tabs'=>$tabs,'parameter_types'=>$types,'template_prepares'=>1,'template_executions'=>2,'result_releases'=>$resultReleases];
} finally {
if (is_resource($db)) {try {$removed=f161Cleanup($db,$owned);} finally {ibase_close($db);}}
}
f161Report('fb161-alias-prepared-filter','Две вкладки остатков одним подготовленным SELECT',$rows,$checks,$observations,$runtime,$owned,$removed);
Ожидаемый результат
Входных параметров — 2
Типы границ — INTEGER / INTEGER
В наличии — Кабель, Клемма
Малый остаток — Лента: 0
Подготовок / выполнений — 1 / 2
Результатов освобождено — 2
Команда освобождена — да
Самостоятельный CLI-файл: одна своя таблица, реальные fbird_* вызовы, ограниченные выборки, result.html/result.json, освобождение ресурсов и удаление своей таблицы. lab.php и README.txt приложены.
Фактический HTML-результат · JSON со значениями и проверками.
Ошибки и границы
Предварительная подготовка позволяет повторно использовать один SQL; без измерения не обещаем ускорения конкретной нагрузки. Native fbird не понимает SQL-параметры :minimum по правилам PDO. Передавайте список значений явно; не подставляйте текст фильтра строковой склейкой. Ноль количества не равен концу чтения: конец — строго false. Каждый выполненный SELECT имеет свой результат, а query живёт до завершения обеих вкладок.
Попробуйте изменить задачу
Что произойдёт при границах 8 и 2 и почему проверки типов недостаточно?
Ожидаемое решение
Оба значения целые и их два, но деловой порядок неправильный. Наш код отклонит минимум больше максимума до execute. Это полезнее необъяснимой пустой вкладки; param_info не заменяет такую проверку.
Одна карточка в массиве, строке CSV и объекте
Шаблон страницы ждёт $row["title"], CSV-экспорт — упорядоченный список, а существующий код виджета — $row->title. Получим одинаковые два товара тремя способами и убедимся, что отсутствующая заметка, намеренно пустая заметка и нулевой остаток не потерялись.
- Один SELECT: title, qty, note
- Первое execute + fetch_assoc → ключи title/qty/note
- Второе execute + fetch_row → позиции 0/1/2
- Третье execute + fetch_object → свойства stdClass
- null, пустой текст и 0 остаются разными значениями
Сначала один шаг
$row = fbird_fetch_assoc($result);
// При успешном чтении: $row["title"].
// Альтернатива на отдельном результате того же SELECT:
$row = fbird_fetch_row($anotherResult);
// $row[0] — первая колонка SELECT.
$item = fbird_fetch_object($thirdResult);
// $item->title — свойство; это не элемент массива.Квадратные скобки обращаются к массиву, стрелка -> — к свойству объекта. Форму выбирают до чтения, исходя из следующего потребителя данных. Три fetch подряд на одном результате прочитали бы три разные строки: здесь для честного сравнения SELECT выполняется заново. В полном файле проверяется false перед доступом к данным. Объект — обычный stdClass без вашего конструктора и методов.
Что получится
| Наблюдение | Результат |
|---|---|
| Ассоциативный ключ title | Кабель |
| Числовая колонка 0 | Кабель |
| Свойство объекта title | Кабель |
| Класс объекта | stdClass |
| Нулевой остаток сохранён | да |
| SQL NULL отличается от пустой строки | да |
| В каждой форме обе строки | да |
<?php
declare(strict_types=1);
require __DIR__.'/lab.php';
$db=null;$owned=$removed=$rows=$checks=$observations=[];
try {
$config=f161Config();$connect=f161Capture(static fn()=>fbird_connect(
$config['database'],$config['user'],$config['password'],'UTF8',0,3));
if (!is_resource($connect['value']) || $connect['warning']) {f161Failure('Соединение не открыто',$connect);}
$db=$connect['value'];unset($connect);$runtime=f161Runtime($db,$config);
function aliasResult161($value,string $operation) {
if (!is_resource($value)) {throw new RuntimeException($operation.': ожидался результат SELECT.');}
return $value;
}
function aliasFreeResult161(&$result): bool {
$call=f161Capture(static fn()=>fbird_free_result($result));$result=null;
if ($call['value']!==true || $call['warning']) {f161Failure('Результат не освобождён',$call);}
return true;
}
function aliasFreeQuery161(&$query): bool {
$call=f161Capture(static fn()=>fbird_free_query($query));$query=null;
if ($call['value']!==true || $call['warning']) {f161Failure('Команда не освобождена',$call);}
return true;
}
function aliasRows161($result,string $shape='assoc'): array {
$rows=[];
while (true) {
$call=f161Capture(static fn()=>match($shape) {
'assoc'=>fbird_fetch_assoc($result),
'row'=>fbird_fetch_row($result),
'object'=>fbird_fetch_object($result),
default=>throw new InvalidArgumentException('Неизвестная форма строки.')
});
if ($call['value']===false) {
if ($call['warning'] || $call['code']!==0) {f161Failure('Чтение прервано',$call);}
break;
}
$rows[]=$call['value'];
}
return $rows;
}
function aliasPrepare161($db,string $sql) {
$call=f161Capture(static fn()=>fbird_prepare($db,$sql));
if (!is_resource($call['value']) || $call['warning']) {f161Failure('Команда не подготовлена',$call);}
return $call['value'];
}
function aliasExecute161($query,array $values) {
$call=f161Capture(static fn()=>fbird_execute($query,...$values));
if ($call['value']===false || $call['warning']) {f161Failure('Команда не выполнена',$call);}
return $call['value'];
}
$name=f161OwnTable($db,$owned,'shapes','(id INTEGER NOT NULL PRIMARY KEY,title VARCHAR(40) CHARACTER SET UTF8 NOT NULL,qty INTEGER NOT NULL,note VARCHAR(40) CHARACTER SET UTF8)');
$q=f161Qualified($name);
f161Command($db,"INSERT INTO $q (id,title,qty,note) VALUES (?,?,?,?)",[1,'Кабель',0,null]);
f161Command($db,"INSERT INTO $q (id,title,qty,note) VALUES (?,?,?,?)",[2,'Клемма',4,'']);
f161Commit($db);
$query=aliasPrepare161($db,"SELECT title AS \"title\",qty AS \"qty\",note AS \"note\" FROM $q WHERE id>=? ORDER BY id ROWS 2");
try {
$views=[];$objectClass='';
foreach (['assoc','row','object'] as $shape) {
$result=aliasResult161(aliasExecute161($query,[1]),'Карточки');
try {
$values=aliasRows161($result,$shape);
if ($shape==='object') {
$objectClass=get_class($values[0]);
$views[$shape]=array_map(static fn($value)=>['title'=>$value->title,'qty'=>$value->qty,'note'=>$value->note],$values);
} else {$views[$shape]=$values;}
} finally {aliasFreeResult161($result);}
}
} finally {$released=aliasFreeQuery161($query);}
$rows=[['Ассоциативный ключ title',$views['assoc'][0]['title']],['Числовая колонка 0',$views['row'][0][0]],
['Свойство объекта title',$views['object'][0]['title']],['Класс объекта',$objectClass],
['Нулевой остаток сохранён',$views['assoc'][0]['qty']===0],['SQL NULL отличается от пустой строки',$views['assoc'][0]['note']===null && $views['assoc'][1]['note']===''],
['В каждой форме обе строки',count($views['assoc'])===2 && count($views['row'])===2 && count($views['object'])===2]];
$expected=[['title'=>'Кабель','qty'=>0,'note'=>null],['title'=>'Клемма','qty'=>4,'note'=>'']];
$checks=['assoc_shape'=>$views['assoc']===$expected,'numeric_shape'=>$views['row']===[['Кабель',0,null],['Клемма',4,'']],
'object_shape'=>$objectClass==='stdClass' && $views['object']===$expected,
'nullable_key_present'=>array_key_exists('note',$views['assoc'][0]),'query_released'=>$released && $query===null];
$observations=['forms'=>$views,'object_class'=>$objectClass,'select_executions'=>3,'each_execution_starts_at_first_row'=>true];
} finally {
if (is_resource($db)) {try {$removed=f161Cleanup($db,$owned);} finally {ibase_close($db);}}
}
f161Report('fb161-alias-result-shapes','Одна карточка в массиве, строке CSV и объекте',$rows,$checks,$observations,$runtime,$owned,$removed);
Ожидаемый результат
Ассоциативный ключ title — Кабель
Числовая колонка 0 — Кабель
Свойство объекта title — Кабель
Класс объекта — stdClass
Нулевой остаток сохранён — да
SQL NULL отличается от пустой строки — да
В каждой форме обе строки — да
Самостоятельный CLI-файл: одна своя таблица, реальные fbird_* вызовы, ограниченные выборки, result.html/result.json, освобождение ресурсов и удаление своей таблицы. lab.php и README.txt приложены.
Фактический HTML-результат · JSON со значениями и проверками.
Ошибки и границы
Регистр имён имеет значение; quoted alias устраняет зависимость шаблона от верхнего регистра исходной колонки. Два одинаковых имени в assoc/object столкнутся: задайте разные AS, например item_id и warehouse_id. Числовая форма сохраняет обе колонки, но требует известного порядка SELECT. isset($row["note"]) для null вернёт false; array_key_exists отличает присутствующее null от отсутствующего ключа. Не применяйте empty к количеству, если 0 — полезное значение.
Разработчик получил из Firebird числовые позиции и ожидал имена колонок. Исходная задача на Stack Overflow. Показываем разницу fetch_row и fetch_assoc на одних данных, а также отдельно описание колонок field_info. Ключи результата определяются выбранной формой чтения и SQL-псевдонимами, а не догадкой по JSON-выводу.
Попробуйте изменить задачу
Как подписать заметки на экране: null как «не заполнено», пустую строку как «очищено пользователем»?
Ожидаемое решение
Сначала сравните $row["note"] === null, затем === "", иначе покажите текст с htmlspecialchars. Эти случаи нельзя склеить одной проверкой empty. Способ чтения строки не заменяет экранирование HTML.
Импорт: связать имена полей с позициями INSERT
Из другого сервиса пришли именованные поля товара в разном порядке, а у одной позиции отсутствует qty. Подготовленный запрос ждёт значения строго id, title, qty. Покажем человеку причину отказа неполной строки, затем сохраним две корректные позиции без перестановки полей и без потери нулевого остатка.
- Вход: title/id/qty могут идти в любом порядке
- INSERT(id,title,qty) → три позиции ?
- Проверка наличия qty → товар 100 отклонён до SQL
- Явный список [id,title,qty] → execute для 101 и 102
- free_query → commit → ограниченный SELECT сохранённых строк
Сначала один шаг
$values = [$item["id"], $item["title"], $item["qty"]];
if (count($values) !== fbird_num_params($query)) {
throw new DomainException("Изменился контракт INSERT");
}
$affected = fbird_execute($query, ...$values);
// Перед этой записью проверить наличие ключей и допустимость значений.Многоточие ... передаёт элементы списка отдельными аргументами. Входной ассоциативный массив нельзя бездумно превратить в array_values: его порядок может отличаться от INSERT. num_params проверяет количество, а param_info помогает увидеть тип представления конкретной позиции. Имена id/title/qty задаёт наше приложение: сам дескриптор параметра может не содержать названия поля.
Что получится
| Наблюдение | Результат |
|---|---|
| Входных мест INSERT | 3 |
| Отклонён товар без поля | 100: qty |
| Сохранены товары | 101, 102 |
| Товар 101 | Муфта: 0 |
| Товар 102 | Кабель: 5 |
| Представление названия | VARCHAR / 80 байт |
| Порядок ключей входа не повредил поля | да |
| Команда INSERT освобождена | да |
<?php
declare(strict_types=1);
require __DIR__.'/lab.php';
$db=null;$owned=$removed=$rows=$checks=$observations=[];
try {
$config=f161Config();$connect=f161Capture(static fn()=>fbird_connect(
$config['database'],$config['user'],$config['password'],'UTF8',0,3));
if (!is_resource($connect['value']) || $connect['warning']) {f161Failure('Соединение не открыто',$connect);}
$db=$connect['value'];unset($connect);$runtime=f161Runtime($db,$config);
function aliasResult161($value,string $operation) {
if (!is_resource($value)) {throw new RuntimeException($operation.': ожидался результат SELECT.');}
return $value;
}
function aliasFreeResult161(&$result): bool {
$call=f161Capture(static fn()=>fbird_free_result($result));$result=null;
if ($call['value']!==true || $call['warning']) {f161Failure('Результат не освобождён',$call);}
return true;
}
function aliasFreeQuery161(&$query): bool {
$call=f161Capture(static fn()=>fbird_free_query($query));$query=null;
if ($call['value']!==true || $call['warning']) {f161Failure('Команда не освобождена',$call);}
return true;
}
function aliasRows161($result,string $shape='assoc'): array {
$rows=[];
while (true) {
$call=f161Capture(static fn()=>match($shape) {
'assoc'=>fbird_fetch_assoc($result),
'row'=>fbird_fetch_row($result),
'object'=>fbird_fetch_object($result),
default=>throw new InvalidArgumentException('Неизвестная форма строки.')
});
if ($call['value']===false) {
if ($call['warning'] || $call['code']!==0) {f161Failure('Чтение прервано',$call);}
break;
}
$rows[]=$call['value'];
}
return $rows;
}
function aliasPrepare161($db,string $sql) {
$call=f161Capture(static fn()=>fbird_prepare($db,$sql));
if (!is_resource($call['value']) || $call['warning']) {f161Failure('Команда не подготовлена',$call);}
return $call['value'];
}
function aliasExecute161($query,array $values) {
$call=f161Capture(static fn()=>fbird_execute($query,...$values));
if ($call['value']===false || $call['warning']) {f161Failure('Команда не выполнена',$call);}
return $call['value'];
}
$name=f161OwnTable($db,$owned,'import','(id INTEGER NOT NULL PRIMARY KEY,title VARCHAR(20) CHARACTER SET UTF8 NOT NULL,qty INTEGER NOT NULL CHECK(qty>=0))');
$q=f161Qualified($name);
$query=aliasPrepare161($db,"INSERT INTO $q (id,title,qty) VALUES (?,?,?)");
try {
$required=['id','title','qty'];$needed=fbird_num_params($query);$parameterDescriptions=[];
for ($i=0;$i<$needed;$i++) {
$info=fbird_param_info($query,$i);
if ($info===false) {throw new RuntimeException('Описание параметра отсутствует.');}
$parameterDescriptions[]=['position'=>$i,'field'=>$required[$i],'type'=>$info['type'],'bytes'=>$info['length']];
}
$input=[['id'=>100,'title'=>'Пропущен остаток'],['qty'=>0,'title'=>'Муфта','id'=>101],['title'=>'Кабель','id'=>102,'qty'=>5]];
$rejected=[];$inserted=[];
foreach ($input as $item) {
$missing=array_values(array_diff($required,array_keys($item)));
if ($missing!==[]) {$rejected[]=['id'=>$item['id'],'missing'=>$missing];continue;}
$values=[$item['id'],$item['title'],$item['qty']];
if (count($values)!==$needed || !is_int($values[0]) || !is_string($values[1]) || !is_int($values[2]) || $values[2]<0) {
throw new DomainException('Неверный контракт строки импорта.');
}
$inserted[]=aliasExecute161($query,$values);
}
} finally {$released=aliasFreeQuery161($query);}
f161Commit($db);
$call=f161Capture(static fn()=>fbird_query($db,"SELECT id AS \"id\",title AS \"title\",qty AS \"qty\" FROM $q WHERE id BETWEEN ? AND ? ORDER BY id ROWS 3",100,102));
if ($call['value']===false || $call['warning']) {f161Failure('Проверка импорта не выполнена',$call);}
$result=aliasResult161($call['value'],'Импорт');unset($call);
try {$saved=aliasRows161($result);} finally {aliasFreeResult161($result);}
$rows=[['Входных мест INSERT',$needed],['Отклонён товар без поля',$rejected[0]['id'].': '.implode(', ',$rejected[0]['missing'])],
['Сохранены товары',implode(', ',array_column($saved,'id'))],['Товар 101',$saved[0]['title'].': '.$saved[0]['qty']],
['Товар 102',$saved[1]['title'].': '.$saved[1]['qty']],['Представление названия',$parameterDescriptions[1]['type'].' / '.$parameterDescriptions[1]['bytes'].' байт'],
['Порядок ключей входа не повредил поля',array_column($saved,'qty')===[0,5]],['Команда INSERT освобождена',$released]];
$checks=['input_count'=>$needed===3,'missing_field_rejected'=>$rejected===[['id'=>100,'missing'=>['qty']]],
'ordered_values_saved'=>$saved===[['id'=>101,'title'=>'Муфта','qty'=>0],['id'=>102,'title'=>'Кабель','qty'=>5]],
'title_descriptor'=>$parameterDescriptions[1]['type']==='VARCHAR' && $parameterDescriptions[1]['bytes']==='80',
'dml_return_counts'=>$inserted===[1,1],'query_released'=>$released && $query===null];
$observations=['saved'=>$saved,'rejected'=>$rejected,'input_contract'=>$parameterDescriptions,'execute_returns'=>$inserted,
'business_field_names_are_application_mapping'=>true];
} finally {
if (is_resource($db)) {try {$removed=f161Cleanup($db,$owned);} finally {ibase_close($db);}}
}
f161Report('fb161-alias-import-contract','Импорт: связать имена полей с позициями INSERT',$rows,$checks,$observations,$runtime,$owned,$removed);
Ожидаемый результат
Входных мест INSERT — 3
Отклонён товар без поля — 100: qty
Сохранены товары — 101, 102
Товар 101 — Муфта: 0
Товар 102 — Кабель: 5
Представление названия — VARCHAR / 80 байт
Порядок ключей входа не повредил поля — да
Команда INSERT освобождена — да
Самостоятельный CLI-файл: одна своя таблица, реальные fbird_* вызовы, ограниченные выборки, result.html/result.json, освобождение ресурсов и удаление своей таблицы. lab.php и README.txt приложены.
Фактический HTML-результат · JSON со значениями и проверками.
Ошибки и границы
VARCHAR(20) в UTF8 описывается длиной 80 байт. Это не разрешение принимать 80 любых символов: проверка длины названия и ограничения предметной области остаются отдельными. Здесь сознательно показана политика частичного импорта: неполная строка пропускается, корректные сохраняются. Если пакет должен приниматься целиком, объедините проверки с транзакцией и отменой всех изменений. Значение 1 от успешного INSERT — число затронутых строк, не идентификатор нового товара. Ошибка SQL не равна пропущенному полю: её нужно диагностировать и не подтверждать ошибочную операцию.
В обсуждении отладки prepared statement хотят увидеть готовую строку SQL; среди предложений есть и пример для native ibase с текстовой подстановкой знаков вопроса. Исходная задача на Stack Overflow. Мы оставляем SQL-шаблон и упорядоченные параметры отдельно. Метаданные позволяют объяснить контракт, но не создают безопасную SQL-строку для повторного исполнения. Значения и секреты не должны попадать в публичный диагностический вывод.
Попробуйте изменить задачу
Сервис добавил ключ category перед id. Нужно ли менять SQL или порядок значений?
Ожидаемое решение
Если этот экран не хранит category, SQL остаётся прежним. Явный список id/title/qty также остаётся прежним. Если новое поле требуется хранить, сначала измените схему и INSERT, затем список и его проверку; одного совпадения количества мало.
Справочник 13 имён для запросов и строк
| Нужно сделать | Карточка |
|---|---|
| Подключить существующее приложение к Firebird. | fbird_connect |
| Выполнить SQL и отделить набор строк от результата изменения. | fbird_query |
| Создать повторно используемый SQL-шаблон. | fbird_prepare |
| Выполнить prepared-команду с очередными значениями. | fbird_execute |
| Прочитать следующую строку по именам колонок. | fbird_fetch_assoc |
| Прочитать следующую строку по порядку SELECT. | fbird_fetch_row |
| Получить следующую строку как stdClass. | fbird_fetch_object |
| Узнать число выходных колонок, не расходуя строку. | fbird_num_fields |
| Прочитать имя, тип и длину выходной колонки. | fbird_field_info |
| Узнать число входных мест prepared-команды. | fbird_num_params |
| Прочитать описание входного параметра по позиции. | fbird_param_info |
| Закончить срок жизни подготовленной команды. | fbird_free_query |
| Освободить результат SELECT, сохранив уже прочитанные данные. | fbird_free_result |
От понятного SELECT к целой операции
Теперь при чтении старого кода можно проследить, где появляется соединение, где подготовленная команда, где результат и где обычные данные PHP. Следующий шаг — транзакции, ошибки и идентификаторы через fbird_*. Для изменения прав служебного пользователя есть отдельная глава доступа, для параметров и ограничений формы — подробный входной контракт.
Новые имена не требуют переписывать рабочие запросы механически. Если проводится рефакторинг, сохраняйте смысл SQL, порядок значений, кодировку, диалект, завершение транзакций и освобождение ресурсов. Эта глава раскрывает перечисленные 13 alias; она не выдаёт их за другой драйвер или за завершение всей ветки Firebird.
Функции и методы этой темы
Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.
fbird_connectПодключить существующее приложение к Firebird.
PHP 5 / PHP 7 < 7.4 исторически; отдельный FirebirdSQL interbase 3.0.1 · interbase
fbird_connect(string $database = "", string $username = "", string $password = "", string $charset = "", int $buffers = 0, int $dialect = 0, string $role = "", int $sync = 0): resource|falseНужен доступ к существующей базе старого приложения, в исходнике которого стоит fbird_connect. Соединение — это ресурс для следующих запросов, а не сами товары. ibase_connect — каноническое имя той же операции. В драйвере FirebirdSQL 3.0.1 fbird_connect зарегистрировано как alias того же C-обработчика; собственного формата ресурсов или отдельного SQL-движка у него нет.
| Параметр / результат | Правило |
|---|---|
| database = "" | Путь к базе на машине сервера или его согласованное имя/alias. Исторические формы: hostname:path для TCP, hostname/port:path для другого порта; //hostname/path относится к старому NetBEUI и не обещает наличие этого транспорта сегодня. Пустое значение в 3.0.1 может дополняться ibase.default_db. |
| username / password = "" | Имя пользователя и его пароль. Пустые значения могут дополняться ibase.default_user/default_password. Секрет приходит из конфигурации, не выводится на страницу и не хранится в публичном примере. Вход и права SELECT — отдельные проверки. |
| charset = "" | Кодировка текста соединения. Для наших UTF-8-строк явно UTF8. Драйвер учитывает ibase.default_charset, если аргумент пуст. Этот параметр не перекодирует произвольный исходный файл и не меняет DDL всех текстовых колонок. |
| buffers = 0 | Запрашиваемое число серверных буферов страниц. 0 или отсутствие оставляет выбор серверу; это не размер PHP-массива. |
| dialect = 0 | SQL-диалект соединения; 0 выбирает текущий поддерживаемый клиентом. Здесь явно 3. Старой базе может требоваться другой диалект: префикс функции этого не исправляет. |
| role = "" | Роль соединения; её имя не выдаёт привилегии само по себе. Историческая страница относит поддержку к InterBase 5 и новее. Firebird требует существующей выданной роли. |
| sync = 0 | Восьмой параметр оставлен без пояснения в исторической странице, но принимается C-кодом 3.0.1: ненулевое значение задаёт force-write, сравнение с синхронным режимом выбирает способ записи. Здесь аргумент опущен, чтобы не изменять настройку надёжности базы. |
| resource / false | Ресурс успешного соединения либо false при отказе. Повтор тех же аргументов может вернуть уже открытое соединение. Обычный connect не означает persistent между запросами; явное закрытие и конец скрипта завершают его обычный срок жизни. |
Версии: историческая страница PHP Manual указывает PHP 5 и PHP 7 до 7.4. Старое встроенное расширение удалено из поставки PHP 7.4; в наших примерах эти имена предоставляет отдельный interbase 3.0.1 для PHP 8.2.35. Наличие функции проверяют в том PHP, который исполняет приложение. Это не метод PDO и не рекомендация менять работающий драйвер только ради другого префикса.
Подключить каталог в UTF8
$db = fbird_connect($database, $user, $password, "UTF8", 0, 3);
if ($db === false) { throw new RuntimeException("База недоступна"); }Так начинается экран наличия. Его результат — две карточки, а не печать ресурса соединения. Неверный путь, недоступный сервер, отказ входа и невозможная кодировка требуют диагностики; сырые сообщения могут раскрывать путь базы. Ошибка преобразования текста может появиться позднее при query/fetch.
Тот же вход для подготовленного импорта
$db = fbird_connect($database, $user, $password, "UTF8", 0, 3);
if ($db === false) { throw new RuntimeException("Импорт не подключён"); }
$query = fbird_prepare($db, $insertSql);Импорт с именованными полями использует то же соединение и затем отдельную команду. Не проверяйте смену пароля повторным connect в том же процессе: возможен повторно используемый ресурс. Проверка настоящего нового входа и права на таблицы разобраны отдельно. Параметры показаны позиционно, потому что историческая arginfo и фактический C-разбор не во всём совпадают.
fbird_queryВыполнить SQL и отделить набор строк от результата изменения.
PHP 5 / PHP 7 < 7.4 исторически; отдельный FirebirdSQL interbase 3.0.1 · interbase
fbird_query([resource $dbOrTransaction, [resource $transaction,]] string $sql, mixed ...$values): resource|int|boolРазовый SELECT нужен, когда SQL выполняется один раз и требуется сразу прочитать результат. Значения можно передать отдельно даже без явного prepare. ibase_query — каноническое имя той же операции. В драйвере FirebirdSQL 3.0.1 fbird_query зарегистрировано как alias того же C-обработчика; собственного формата ресурсов или отдельного SQL-движка у него нет.
| Параметр / результат | Правило |
|---|---|
| Формы вызова | fbird_query($sql, ...$values); fbird_query($dbOrTransaction, $sql, ...$values); fbird_query($db, $transaction, $sql, ...$values). При отсутствии ресурса используется последнее соединение; без явной транзакции — его транзакция по умолчанию. |
| sql / values | Строка SQL и последовательные значения для ?. Это mixed-значения, а не только int из сокращённой исторической сигнатуры. Имена таблиц/полей и ORDER BY не являются параметрами значений: их выбирают из разрешённого приложением набора. |
| Возврат | SELECT, в том числе пустой, даёт ресурс результата. INSERT/UPDATE/DELETE без возвращаемого набора дают положительное число затронутых строк, а успешная операция без затронутых строк — true. Успешная команда без набора также может вернуть true. false — отказ; сравнивайте строго, а не через if (!$value). Если SQL возвращает набор, сначала обработайте ресурс. |
| Ошибки | Проверяйте false и сохраняйте диагностику до другого вызова. Кодировка, синтаксис, ограничения и права проверяются настоящим сервером; alias не обходит их. Неверный ресурс отдельно может вызвать ошибку PHP. |
Версии: историческая страница PHP Manual указывает PHP 5 и PHP 7 до 7.4. Старое встроенное расширение удалено из поставки PHP 7.4; в наших примерах эти имена предоставляет отдельный interbase 3.0.1 для PHP 8.2.35. Наличие функции проверяют в том PHP, который исполняет приложение. Это не метод PDO и не рекомендация менять работающий драйвер только ради другого префикса.
Данные для экрана
$result = fbird_query($db, 'SELECT title AS "title",qty AS "qty" FROM items WHERE active=? AND qty>=? ORDER BY id ROWS 2', 1, 1);В экране наличия условия и лимит применяет Firebird. Перед fetch проверьте resource/false. Пустой набор — действующий результат, у которого первый fetch даст false без ошибки.
Убедиться, что импорт сохранился
$result = fbird_query($db, "SELECT id,title,qty FROM items WHERE id BETWEEN ? AND ? ORDER BY id ROWS 3", 100, 102);В проверке импорта этот SELECT выполняется после commit и выдаёт только 101 и 102. Его ресурс освобождается отдельно. Сама query не является обещанием подтверждения всей бизнес-операции: управляйте транзакцией явно. Исторический специальный режим IBASE_CREATE для CREATE DATABASE также существует в реализации, но не нужен для чтения и не должен принимать произвольную строку пользователя.
fbird_prepareСоздать повторно используемый SQL-шаблон.
PHP 5 / PHP 7 < 7.4 исторически; отдельный FirebirdSQL interbase 3.0.1 · interbase
fbird_prepare(string $sql): resource|false; fbird_prepare(resource $dbOrTransaction, string $sql): resource|false; fbird_prepare(resource $db, resource $transaction, string $sql): resource|falseПри одинаковом SQL с меняющимися значениями полезно один раз подготовить команду и затем выполнять её многократно. Подготовка описывает входные места и выходные колонки до чтения строк. ibase_prepare — каноническое имя той же операции. В драйвере FirebirdSQL 3.0.1 fbird_prepare зарегистрировано как alias того же C-обработчика; собственного формата ресурсов или отдельного SQL-движка у него нет.
| Параметр / результат | Правило |
|---|---|
| Формы вызова | fbird_prepare($sql); fbird_prepare($dbOrTransaction,$sql); fbird_prepare($db,$transaction,$sql). Вторая форма принимает соединение или транзакцию; третья — оба ресурса. При пропуске используются последнее соединение и его транзакция по умолчанию. |
| sql | SQL-шаблон с позиционными ?. Параметризуются значения, а не имя таблицы/поля. Значения ещё не передаются; синтаксис и возможность подготовки проверяются сервером. |
| transaction | Ресурс транзакции, не строка: историческое отображение сигнатуры содержит неточный string. Подготовленная команда связана с этим контекстом. |
| resource / false | Ресурс prepared-команды либо false. Это не result для fetch. При ошибке сохраняйте сообщение/код сразу; закрытый или чужой тип ресурса не подходит. После последнего execute нужно free_query. |
Версии: историческая страница PHP Manual указывает PHP 5 и PHP 7 до 7.4. Старое встроенное расширение удалено из поставки PHP 7.4; в наших примерах эти имена предоставляет отдельный interbase 3.0.1 для PHP 8.2.35. Наличие функции проверяют в том PHP, который исполняет приложение. Это не метод PDO и не рекомендация менять работающий драйвер только ради другого префикса.
Подготовить диапазон остатков
$query = fbird_prepare($db, "SELECT title,qty FROM items WHERE qty BETWEEN ? AND ? ORDER BY id");
if ($query === false) { throw new RuntimeException("Нельзя подготовить диапазон"); }Две вкладки используют один query для диапазонов 2…8 и 0…1. Положения 0 и 1 остаются минимумом и максимумом при каждом execute; одинаковый тип INTEGER не выражает этот смысл.
Подготовить строку приёмки товаров
$query = fbird_prepare($db, "INSERT INTO items (id,title,qty) VALUES (?,?,?)");
if ($query === false) { throw new RuntimeException("Нельзя подготовить импорт"); }
$needed = fbird_num_params($query); // 3В импорте подготовка делается до цикла входных строк. Освободить команду нужно и при отказе последующей проверки: finally охватывает весь её срок жизни. Подготовка сама не сохраняет товар и не возвращает его ID.
fbird_executeВыполнить prepared-команду с очередными значениями.
PHP 5 / PHP 7 < 7.4 исторически; отдельный FirebirdSQL interbase 3.0.1 · interbase
fbird_execute(resource $query, mixed ...$values): resource|int|boolКогда шаблон уже подготовлен, execute связывает очередные значения с его местами и выполняет команду. ibase_execute — каноническое имя той же операции. В драйвере FirebirdSQL 3.0.1 fbird_execute зарегистрировано как alias того же C-обработчика; собственного формата ресурсов или отдельного SQL-движка у него нет.
| Параметр / результат | Правило |
|---|---|
| query | Действующий ресурс из fbird_prepare/ibase_prepare. Ресурсы совместимы, потому что имена ведут в один обработчик. |
| ...values | Значения отдельными позиционными аргументами; для готового числового списка используйте ...$values. Передавать ассоциативные поля как именованные аргументы PHP — не то же самое, что связывать SQL :name. |
| Возврат | SELECT, в том числе пустой, даёт ресурс результата. INSERT/UPDATE/DELETE без возвращаемого набора дают положительное число затронутых строк, а успешная операция без затронутых строк — true. Успешная команда без набора также может вернуть true. false — отказ; сравнивайте строго, а не через if (!$value). Если SQL возвращает набор, сначала обработайте ресурс. |
| Число значений и ошибки | В 3.0.1 недостаток значений вызывает предупреждение и false; избыток сообщает notice, поэтому не рассчитывайте на молчаливое игнорирование. Проверяйте точное количество сами. Ограничения данных и SQL-ошибки сохраняйте сразу; положительное число не является новым ID. |
Версии: историческая страница PHP Manual указывает PHP 5 и PHP 7 до 7.4. Старое встроенное расширение удалено из поставки PHP 7.4; в наших примерах эти имена предоставляет отдельный interbase 3.0.1 для PHP 8.2.35. Наличие функции проверяют в том PHP, который исполняет приложение. Это не метод PDO и не рекомендация менять работающий драйвер только ради другого префикса.
Переключить вкладку
$result = fbird_execute($query, 2, 8);
// Прочитать/освободить результат.
$result = fbird_execute($query, 0, 1);Подготовленный фильтр сначала возвращает Кабель и Клемму, затем Ленту с нулевым остатком. Освобождается каждый result; общий query остаётся до окончания второй вкладки.
Сохранить именованные данные в порядке SQL
$values = [$item["id"], $item["title"], $item["qty"]];
$affected = fbird_execute($query, ...$values);
if ($affected === false) { throw new RuntimeException("Товар не сохранён"); }Это сохранение товаров 101 и 102. На каждом INSERT получено 1. После всех успешных записей отдельно выполнен commit. Если требование — принять пакет целиком, не подтверждайте частичный набор после исключения.
fbird_fetch_assocПрочитать следующую строку по именам колонок.
PHP 5 / PHP 7 < 7.4 исторически; отдельный FirebirdSQL interbase 3.0.1 · interbase
fbird_fetch_assoc(resource $result, int $fetch_flag = 0): array|falseИменованные ключи удобны для карточки страницы: название читается как $row["title"], без зависимости от номера колонки. ibase_fetch_assoc — каноническое имя той же операции. В драйвере FirebirdSQL 3.0.1 fbird_fetch_assoc зарегистрировано как alias того же C-обработчика; собственного формата ресурсов или отдельного SQL-движка у него нет.
| Параметр / результат | Правило |
|---|---|
| result | Действующий ресурс результата SELECT из query/execute. Каждый вызов читает следующую строку и продвигает курсор; метаданные num_fields/field_info его не продвигают. |
| fetch_flag = 0 | Без флагов BLOB представлен ID, даты/время — строками настроенного формата. IBASE_TEXT (современное имя IBASE_FETCH_BLOBS) просит содержимое BLOB; IBASE_UNIXTIME — числовое представление даты/времени. Флаги объединяют |. Выбранный драйвер также поддерживает IBASE_FETCH_ARRAYS для SQL ARRAY. Большой BLOB/ARRAY при этом целиком попадает в память. |
| Возврат | Возвращается ассоциативный массив одной строки. SQL NULL остаётся null; пустой текст и 0 имеют собственные значения. Строго false обозначает конец набора либо ошибку чтения. |
| Ошибки и границы | После false сразу снимите код/предупреждение: нулевой код без предупреждения в наших программах означает EOF. Закрытый результат или неверный тип аргумента — ошибка обращения к API, а не пустая выборка. Не продолжайте fetch после free_result. |
Версии: историческая страница PHP Manual указывает PHP 5 и PHP 7 до 7.4. Старое встроенное расширение удалено из поставки PHP 7.4; в наших примерах эти имена предоставляет отдельный interbase 3.0.1 для PHP 8.2.35. Наличие функции проверяют в том PHP, который исполняет приложение. Это не метод PDO и не рекомендация менять работающий драйвер только ради другого префикса.
Вывести первую карточку
$row = fbird_fetch_assoc($result);
if ($row !== false) { echo $row["title"], ": ", $row["qty"]; }В каталоге первая строка — Кабель: 3. Для всех строк повторяют fetch в цикле, а false разбирают с немедленной диагностикой. Не вставляйте отдельный пробный fetch перед основным циклом.
Различить отсутствующую заметку и пустую
$row = fbird_fetch_assoc($result);
if ($row !== false && array_key_exists("note", $row)) {
$label = $row["note"] === null ? "не заполнено" : ($row["note"] === "" ? "очищено" : $row["note"]);
}Одинаковые товары в трёх формах сохраняют note=null у первого и note="" у второго. Повторяющиеся названия колонок перезаписываются последним: используйте разные AS или fetch_row. Alias в двойных кавычках фиксирует регистр ключа.
Флаг IBASE_UNIXTIME нельзя считать обещанием UTC: в закреплённом Windows-драйвере преобразование использует нативное время процесса; отдельный TIME в проверке дал -1. Разбор времён с явной зоной и список флагов разобраны в настройках Firebird. Для больших вложений используйте порционное чтение BLOB, а не автоматическую загрузку всего содержимого. Форму строки выбирают независимо от её экранирования для HTML или правил экспорта CSV.
fbird_fetch_rowПрочитать следующую строку по порядку SELECT.
PHP 5 / PHP 7 < 7.4 исторически; отдельный FirebirdSQL interbase 3.0.1 · interbase
fbird_fetch_row(resource $result, int $fetch_flag = 0): array|falseЧисловая строка удобна для фиксированного порядка колонок файла выгрузки. Её индексы идут от нуля в порядке SELECT. ibase_fetch_row — каноническое имя той же операции. В драйвере FirebirdSQL 3.0.1 fbird_fetch_row зарегистрировано как alias того же C-обработчика; собственного формата ресурсов или отдельного SQL-движка у него нет.
| Параметр / результат | Правило |
|---|---|
| result | Действующий ресурс результата SELECT из query/execute. Каждый вызов читает следующую строку и продвигает курсор; метаданные num_fields/field_info его не продвигают. |
| fetch_flag = 0 | Без флагов BLOB представлен ID, даты/время — строками настроенного формата. IBASE_TEXT (современное имя IBASE_FETCH_BLOBS) просит содержимое BLOB; IBASE_UNIXTIME — числовое представление даты/времени. Флаги объединяют |. Выбранный драйвер также поддерживает IBASE_FETCH_ARRAYS для SQL ARRAY. Большой BLOB/ARRAY при этом целиком попадает в память. |
| Возврат | Возвращается числовой массив одной строки: [0], [1], … . SQL NULL остаётся null; пустой текст и 0 имеют собственные значения. Строго false обозначает конец набора либо ошибку чтения. |
| Ошибки и границы | После false сразу снимите код/предупреждение: нулевой код без предупреждения в наших программах означает EOF. Закрытый результат или неверный тип аргумента — ошибка обращения к API, а не пустая выборка. Не продолжайте fetch после free_result. |
Версии: историческая страница PHP Manual указывает PHP 5 и PHP 7 до 7.4. Старое встроенное расширение удалено из поставки PHP 7.4; в наших примерах эти имена предоставляет отдельный interbase 3.0.1 для PHP 8.2.35. Наличие функции проверяют в том PHP, который исполняет приложение. Это не метод PDO и не рекомендация менять работающий драйвер только ради другого префикса.
Прочитать две колонки вкладки
$row = fbird_fetch_row($result);
if ($row !== false) { echo $row[0], ": ", $row[1]; }В диапазоне остатков SELECT содержит title,qty, поэтому $row[0] — название. Это массив, обращение $row->title к нему неверно. Изменив список SELECT, обновите потребителя.
Получить порядок полей для CSV
$row = fbird_fetch_row($result);
// SELECT title,qty,note: ["Кабель", 0, null].
// Перед fputcsv явно выбрать представление null: например "не заполнено".Сравнение форм показывает исходные значения для такой выгрузки. Числовые позиции позволяют сохранить два одноимённых поля JOIN; это не даёт им бизнес-названий. Заголовки берут из собственного контракта или field_info, не из попытки прочитать дополнительную строку.
Флаг IBASE_UNIXTIME нельзя считать обещанием UTC: в закреплённом Windows-драйвере преобразование использует нативное время процесса; отдельный TIME в проверке дал -1. Разбор времён с явной зоной и список флагов разобраны в настройках Firebird. Для больших вложений используйте порционное чтение BLOB, а не автоматическую загрузку всего содержимого. Форму строки выбирают независимо от её экранирования для HTML или правил экспорта CSV.
fbird_fetch_objectПолучить следующую строку как stdClass.
PHP 5 / PHP 7 < 7.4 исторически; отдельный FirebirdSQL interbase 3.0.1 · interbase
fbird_fetch_object(resource $result, int $fetch_flag = 0): object|falseЕсли существующий шаблон читает $item->title, следующую строку можно получить объектом с именованными свойствами. ibase_fetch_object — каноническое имя той же операции. В драйвере FirebirdSQL 3.0.1 fbird_fetch_object зарегистрировано как alias того же C-обработчика; собственного формата ресурсов или отдельного SQL-движка у него нет.
| Параметр / результат | Правило |
|---|---|
| result | Действующий ресурс результата SELECT из query/execute. Каждый вызов читает следующую строку и продвигает курсор; метаданные num_fields/field_info его не продвигают. |
| fetch_flag = 0 | Без флагов BLOB представлен ID, даты/время — строками настроенного формата. IBASE_TEXT (современное имя IBASE_FETCH_BLOBS) просит содержимое BLOB; IBASE_UNIXTIME — числовое представление даты/времени. Флаги объединяют |. Выбранный драйвер также поддерживает IBASE_FETCH_ARRAYS для SQL ARRAY. Большой BLOB/ARRAY при этом целиком попадает в память. |
| Возврат | Возвращается stdClass с полями результата в свойствах. Класса приложения, методов и пользовательского конструктора эта функция не принимает. SQL NULL остаётся null; пустой текст и 0 имеют собственные значения. Строго false обозначает конец набора либо ошибку чтения. |
| Ошибки и границы | После false сразу снимите код/предупреждение: нулевой код без предупреждения в наших программах означает EOF. Закрытый результат или неверный тип аргумента — ошибка обращения к API, а не пустая выборка. Не продолжайте fetch после free_result. |
Версии: историческая страница PHP Manual указывает PHP 5 и PHP 7 до 7.4. Старое встроенное расширение удалено из поставки PHP 7.4; в наших примерах эти имена предоставляет отдельный interbase 3.0.1 для PHP 8.2.35. Наличие функции проверяют в том PHP, который исполняет приложение. Это не метод PDO и не рекомендация менять работающий драйвер только ради другого префикса.
Карточка старого виджета
$item = fbird_fetch_object($result);
if ($item !== false) { echo $item->title, ": ", $item->qty; }В трёх формах карточки это Кабель: 0. Для свойства title SQL использует AS "title". Никакой дополнительной бизнес-логики при создании stdClass не исполняется.
Замечание оператора
$item = fbird_fetch_object($result);
if ($item !== false && property_exists($item, "note")) {
$unsetNote = $item->note === null;
$clearedNote = $item->note === "";
}На двух строках видны разные состояния заметки. Одноимённые колонки сталкиваются так же, как у fetch_assoc: последний столбец займёт свойство. Это не ORM: объект не сохраняет изменения обратно в базу при присваивании $item->qty.
Флаг IBASE_UNIXTIME нельзя считать обещанием UTC: в закреплённом Windows-драйвере преобразование использует нативное время процесса; отдельный TIME в проверке дал -1. Разбор времён с явной зоной и список флагов разобраны в настройках Firebird. Для больших вложений используйте порционное чтение BLOB, а не автоматическую загрузку всего содержимого. Форму строки выбирают независимо от её экранирования для HTML или правил экспорта CSV.
fbird_num_fieldsУзнать число выходных колонок, не расходуя строку.
PHP 5 / PHP 7 < 7.4 исторически; отдельный FirebirdSQL interbase 3.0.1 · interbase
fbird_num_fields(resource $result): intПеред построением таблицы результата полезно узнать, сколько колонок предусмотрено SELECT. Число товаров здесь ни при чём. ibase_num_fields — каноническое имя той же операции. В драйвере FirebirdSQL 3.0.1 fbird_num_fields зарегистрировано как alias того же C-обработчика; собственного формата ресурсов или отдельного SQL-движка у него нет.
| Параметр / результат | Правило |
|---|---|
| result | Официальный контракт принимает результат query/execute. C-реализация 3.0.1 также читает выходной дескриптор подготовленной команды. Ресурс должен быть действующим и подходящего типа. |
| int | Количество выходных колонок; при отсутствии выходного дескриптора реализация возвращает 0. Даже пустой SELECT сохраняет число своих колонок. Это не row count и не количество входных ?. |
| Ошибки | Не передавайте false от неуспешного запроса и не считайте ошибку PHP нулём колонок. Вызов не читает и не пропускает строку. |
Версии: историческая страница PHP Manual указывает PHP 5 и PHP 7 до 7.4. Старое встроенное расширение удалено из поставки PHP 7.4; в наших примерах эти имена предоставляет отдельный interbase 3.0.1 для PHP 8.2.35. Наличие функции проверяют в том PHP, который исполняет приложение. Это не метод PDO и не рекомендация менять работающий драйвер только ради другого префикса.
Создать заголовки экрана
$columns = fbird_num_fields($result);
for ($i=0; $i<$columns; $i++) {
$info = fbird_field_info($result, $i);
// Проверить false, использовать alias для заголовка.
}В каталоге три колонки: id,title,qty. Затем читаются обе строки, включая первую. Заголовки получили из описания, не пожертвовав товаром ради образца.
Проверить формат выгрузки
$columns = fbird_num_fields($result);
if ($columns !== 3) { throw new DomainException("Ожидались title, qty, note"); }Для числовой формы карточки ожидаются три колонки. Такая проверка выявит добавленный столбец, но не обмен title и note местами: дополните её проверкой alias через field_info. Две строки и три колонки — независимые числа.
fbird_field_infoПрочитать имя, тип и длину выходной колонки.
PHP 5 / PHP 7 < 7.4 исторически; отдельный FirebirdSQL interbase 3.0.1 · interbase
fbird_field_info(resource $result, int $field_number): array|falseЧтобы подписать или проверить колонки результата, нужно их описание, а не случайные значения первого товара. ibase_field_info — каноническое имя той же операции. В драйвере FirebirdSQL 3.0.1 fbird_field_info зарегистрировано как alias того же C-обработчика; собственного формата ресурсов или отдельного SQL-движка у него нет.
| Параметр / результат | Правило |
|---|---|
| result / field_number | Действующий result и целый индекс колонки от 0 до num_fields-1. Реализация 3.0.1 допускает выходной дескриптор prepared-команды. |
| array / false | Массив описания. При индексе вне диапазона — false, без обязательного предупреждения; при отсутствии выходного дескриптора 3.0.1 также сообщает диагностическую ошибку. Неверный ресурс обрабатывается отдельно. |
| name / alias / relation | Исходное имя, псевдоним и имя отношения из дескриптора. Выражения могут не иметь relation/name; у параметров часто пусты все три значения. |
| length | Длина представления в байтах; в 3.0.1 это строка, например "80". Не число символов и не полное правило формы. |
| type | Строковое описание типа, например INTEGER/VARCHAR/NUMERIC(18,2). Оно может отражать хранение и масштаб, а не буквально исходный DDL. |
| Числовые ключи | Драйвер добавляет 0…4 с теми же значениями наряду с именованными. Для ясности используйте именованные поля, не считайте десять элементов десятью свойствами. |
Версии: историческая страница PHP Manual указывает PHP 5 и PHP 7 до 7.4. Старое встроенное расширение удалено из поставки PHP 7.4; в наших примерах эти имена предоставляет отдельный interbase 3.0.1 для PHP 8.2.35. Наличие функции проверяют в том PHP, который исполняет приложение. Это не метод PDO и не рекомендация менять работающий драйвер только ради другого префикса.
Подпись количества
$info = fbird_field_info($result, 2);
if ($info === false) { throw new RuntimeException("Третьей колонки нет"); }
echo $info["alias"]; // qty для SELECT id,title,qtyЭто третья колонка экрана наличия. Она читается без перемещения курсора, поэтому первый товар не пропадёт.
Защитить CSV от перестановки столбцов
$expected = ["title", "qty", "note"];
foreach ($expected as $index=>$alias) {
$info = fbird_field_info($result, $index);
if ($info === false || $info["alias"] !== $alias) {
throw new DomainException("Изменился формат выгрузки");
}
}Это прикладная проверка SELECT из сценария форм строки. Метаданные не содержат полного набора CHECK/внешних ключей/прав: не генерируйте по ним всю бизнес-форму. Входные места INSERT описывает другая функция — fbird_param_info.
fbird_num_paramsУзнать число входных мест prepared-команды.
PHP 5 / PHP 7 < 7.4 исторически; отдельный FirebirdSQL interbase 3.0.1 · interbase
fbird_num_params(resource $query): intДо execute можно объяснить, сколько значений нужно подготовленному фильтру или импорту. ibase_num_params — каноническое имя той же операции. В драйвере FirebirdSQL 3.0.1 fbird_num_params зарегистрировано как alias того же C-обработчика; собственного формата ресурсов или отдельного SQL-движка у него нет.
| Параметр / результат | Правило |
|---|---|
| query | Действующий prepared-ресурс из prepare, а не result SELECT и не строка SQL. |
| int | Число входных мест связывания. 0 допустим для шаблона без ?. Число берётся из разобранного сервером дескриптора, не подсчётом символов. Литерал '?' не является параметром. |
| Ошибки и предел | Неверный/закрытый ресурс может дать ошибку PHP. Число не объясняет порядок, тип и смысл значений; равные количества не доказывают правильность запроса. |
Версии: историческая страница PHP Manual указывает PHP 5 и PHP 7 до 7.4. Старое встроенное расширение удалено из поставки PHP 7.4; в наших примерах эти имена предоставляет отдельный interbase 3.0.1 для PHP 8.2.35. Наличие функции проверяют в том PHP, который исполняет приложение. Это не метод PDO и не рекомендация менять работающий драйвер только ради другого префикса.
Две границы вкладки
$needed = fbird_num_params($query);
$values = [2, 8];
if (count($values) !== $needed) { throw new DomainException("Нужны две границы"); }В диапазоне остатков needed=2. Дополнительно проверяется minimum<=maximum, потому что число мест не обнаруживает перестановку.
Изменившийся импорт
$needed = fbird_num_params($query);
$values = [$item["id"], $item["title"], $item["qty"]];
if (count($values) !== $needed) { throw new DomainException("Список полей не совпал с INSERT"); }В импорте needed=3. Отсутствие ключа qty проверяется до построения $values; иначе PHP уже сообщит о неизвестном ключе. Имена входных полей сопоставляются с SQL нашим явным списком.
fbird_param_infoПрочитать описание входного параметра по позиции.
PHP 5 / PHP 7 < 7.4 исторически; отдельный FirebirdSQL interbase 3.0.1 · interbase
fbird_param_info(resource $query, int $param_number): array|falseЕсли prepared-команда ожидает другое представление, описание конкретного входного места поможет локализовать несовпадение до execute. ibase_param_info — каноническое имя той же операции. В драйвере FirebirdSQL 3.0.1 fbird_param_info зарегистрировано как alias того же C-обработчика; собственного формата ресурсов или отдельного SQL-движка у него нет.
| Параметр / результат | Правило |
|---|---|
| query / param_number | Действующий prepared-ресурс и целый индекс от 0 до num_params-1. Третье входное место имеет индекс 2. |
| array / false | Описание входного параметра; при отсутствии входного дескриптора или индексе вне диапазона в 3.0.1 — false, не обязательно с SQL-ошибкой. Историческая сигнатура сокращена до array. |
| name / alias / relation | Исходное имя, псевдоним и имя отношения из дескриптора. Выражения могут не иметь relation/name; у параметров часто пусты все три значения. |
| length | Длина представления в байтах; в 3.0.1 это строка, например "80". Не число символов и не полное правило формы. |
| type | Строковое описание типа, например INTEGER/VARCHAR/NUMERIC(18,2). Оно может отражать хранение и масштаб, а не буквально исходный DDL. |
| Числовые ключи | Драйвер добавляет 0…4 с теми же значениями наряду с именованными. Для ясности используйте именованные поля, не считайте десять элементов десятью свойствами. |
Версии: историческая страница PHP Manual указывает PHP 5 и PHP 7 до 7.4. Старое встроенное расширение удалено из поставки PHP 7.4; в наших примерах эти имена предоставляет отдельный interbase 3.0.1 для PHP 8.2.35. Наличие функции проверяют в том PHP, который исполняет приложение. Это не метод PDO и не рекомендация менять работающий драйвер только ради другого префикса.
Объяснить название товара
$info = fbird_param_info($query, 1);
if ($info === false) { throw new RuntimeException("Второго параметра нет"); }
echo $info["type"], " / ", $info["length"]; // VARCHAR / 80В импорте title объявлен VARCHAR(20) CHARACTER SET UTF8. Дескриптор 80 байт не означает 80 допустимых символов. Название title известно из контракта приложения, а не гарантируется полем name этого массива.
Диагностика обеих границ
$minimum = fbird_param_info($query, 0);
$maximum = fbird_param_info($query, 1);
// После проверки false: оба type равны INTEGER.В фильтре остатков это одинаковые типы разных по смыслу мест. Полный разбор метаданных и ограничений формы объясняет также DECIMAL: представление NUMERIC(18,2) не восстанавливает буквальный DDL и не заменяет явный CHECK бизнес-лимита.
fbird_free_queryЗакончить срок жизни подготовленной команды.
PHP 5 / PHP 7 < 7.4 исторически; отдельный FirebirdSQL interbase 3.0.1 · interbase
fbird_free_query(resource $query): boolПосле последнего execute нужно освободить prepared-команду, чтобы следующий этап не держал её ресурсы без необходимости. ibase_free_query — каноническое имя той же операции. В драйвере FirebirdSQL 3.0.1 fbird_free_query зарегистрировано как alias того же C-обработчика; собственного формата ресурсов или отдельного SQL-движка у него нет.
| Параметр / результат | Правило |
|---|---|
| query | Ресурс из prepare. Результаты каждого SELECT сначала читаются и освобождаются отдельно через free_result. |
| bool | true при освобождении; false по контракту отказа. Неверный аргумент/закрытый ресурс отдельно может вызвать ошибку PHP. После успеха поставьте переменной null и не вызывайте execute повторно. |
| Что не происходит | free_query не делает commit/rollback, не удаляет товар или таблицу, не закрывает соединение. Скопированные PHP-данные продолжают существовать. |
Версии: историческая страница PHP Manual указывает PHP 5 и PHP 7 до 7.4. Старое встроенное расширение удалено из поставки PHP 7.4; в наших примерах эти имена предоставляет отдельный interbase 3.0.1 для PHP 8.2.35. Наличие функции проверяют в том PHP, который исполняет приложение. Это не метод PDO и не рекомендация менять работающий драйвер только ради другого префикса.
Закончить обе вкладки
try {
// execute первого диапазона → чтение → free_result.
// execute второго диапазона → чтение → free_result.
} finally {
$ok = fbird_free_query($query);
$query = null;
if ($ok !== true) { throw new RuntimeException("Команда не освобождена"); }
}В двух вкладках prepare выполняется один раз, а free_query только после обоих результатов. Этот порядок не обещает исправить любую историческую утечку; он явно ограничивает срок жизни ресурсов.
Освободить INSERT перед подтверждением
try {
// Проверить вход и выполнить INSERT для принятых строк.
} finally {
fbird_free_query($query);
$query = null;
}
// Отдельный commit после успешной бизнес-операции.В импорте после закрытия команды и commit другой SELECT всё ещё видит товары 101 и 102. Полный файл проверяет успешное освобождение; сокращённый фрагмент показывает порядок. При исключении не подменяйте очистку ресурсов подтверждением частично выполненного пакета.
fbird_free_resultОсвободить результат SELECT, сохранив уже прочитанные данные.
PHP 5 / PHP 7 < 7.4 исторически; отдельный FirebirdSQL interbase 3.0.1 · interbase
fbird_free_result(resource $result): boolПрочитанные строки уже могут лежать в PHP-массиве. Серверный результат SELECT после этого освобождается отдельно. ibase_free_result — каноническое имя той же операции. В драйвере FirebirdSQL 3.0.1 fbird_free_result зарегистрировано как alias того же C-обработчика; собственного формата ресурсов или отдельного SQL-движка у него нет.
| Параметр / результат | Правило |
|---|---|
| result | Действующий результат query/execute; не prepared-команда, не соединение и не массив прочитанных строк. |
| bool | true при освобождении, false по контракту отказа. Ошибки ресурса могут проявиться на уровне PHP. После вызова не fetch и не повторное free; обнулите переменную. |
| Граница | Функция не удаляет выбранные записи и не подтверждает транзакцию. Для повторяемого prepared-запроса его query остаётся открытым до free_query. |
Версии: историческая страница PHP Manual указывает PHP 5 и PHP 7 до 7.4. Старое встроенное расширение удалено из поставки PHP 7.4; в наших примерах эти имена предоставляет отдельный interbase 3.0.1 для PHP 8.2.35. Наличие функции проверяют в том PHP, который исполняет приложение. Это не метод PDO и не рекомендация менять работающий драйвер только ради другого префикса.
Сохранить данные страницы, закрыть результат
try {
$items = aliasRows161($result); // Читает ограниченный SELECT.
} finally {
$ok = fbird_free_result($result);
$result = null;
if ($ok !== true) { throw new RuntimeException("Результат не освобождён"); }
}
// $items по-прежнему содержит прочитанные товары.Это экран наличия. aliasRows161 — показанная в полном файле обёртка над fetch с немедленной диагностикой, не функция расширения. Массив данных и ресурс результата — разные вещи.
Перейти к следующей форме строки
$result = fbird_execute($query, 1);
// Прочитать в форме assoc.
fbird_free_result($result);
$result = null;
$result = fbird_execute($query, 1);
// Новый результат для формы row начинается с первой строки.В сравнении форм так прочитаны одинаковые товары, а не последовательно потеряны разные строки одного курсора. Полный файл проверяет все возвраты и закрывает результат в finally. Не оставляйте ссылки на старые ресурсы перед удалением собственной учебной таблицы.
Источники и обсуждения
- PHP Manual — fbird_connect
- PHP Manual — ibase_connect
- PHP Manual — fbird_query
- PHP Manual — ibase_query
- PHP Manual — fbird_prepare
- PHP Manual — ibase_prepare
- PHP Manual — fbird_execute
- PHP Manual — ibase_execute
- PHP Manual — fbird_fetch_assoc
- PHP Manual — ibase_fetch_assoc
- PHP Manual — fbird_fetch_row
- PHP Manual — ibase_fetch_row
- PHP Manual — fbird_fetch_object
- PHP Manual — ibase_fetch_object
- PHP Manual — fbird_num_fields
- PHP Manual — ibase_num_fields
- PHP Manual — fbird_field_info
- PHP Manual — ibase_field_info
- PHP Manual — fbird_num_params
- PHP Manual — ibase_num_params
- PHP Manual — fbird_param_info
- PHP Manual — ibase_param_info
- PHP Manual — fbird_free_query
- PHP Manual — ibase_free_query
- PHP Manual — fbird_free_result
- PHP Manual — ibase_free_result
- FirebirdSQL 3.0.1 — alias и соединение
- FirebirdSQL 3.0.1 — обработчики запросов
Код и руководство с собой
Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.
Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.
Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.


