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

Дерево руководства
Глава 82 · После основ PHP и массивов
CUBRID: первый каталог, нужная выборка и понятная ошибка подключения
От первого сохранённого товара до ограниченного SQL-экрана, URL-подключения и понятной диагностики отказа.
От складского экрана к таблице, соединению и SQL
Представьте экран склада: «Кабель USB — 6», «Предохранитель 10A — 0». Эти данные должны сохраняться между запусками PHP, а разные страницы должны получать согласованные сведения. Для этого данные хранят в базе, а PHP запрашивает нужную часть. CUBRID — отдельная реляционная СУБД: она хранит таблицы, исполняет SQL, поддерживает транзакции и права. Здесь мы осваиваем её native-расширение cubrid_* на четырёх законченных действиях.
| Понятие | Что это в нашем каталоге |
|---|---|
| База данных | phpmanual165 — отдельная учебная область на сервере, содержащая таблицы. Это не PHP-массив и не HTML-файл. |
| Таблица | Набор товаров с заранее описанными столбцами. В каждом запуске имя собственное и случайное; products в коротких фрагментах означает уже созданную таблицу. |
| Строка | Один товар: id=1, sku=USB-165, title=Кабель USB, qty=6. |
| Столбец и тип | qty INT хранит целое количество; title VARCHAR(120) — текст с ограничением; note допускает SQL NULL, то есть отсутствие значения. |
| PRIMARY KEY / UNIQUE | id однозначно выбирает товар, UNIQUE у sku не позволяет двум строкам случайно получить одинаковый артикул. Это не автоматическое создание связей между любыми похожими значениями. |
| Соединение и запрос | Соединение даёт доступ к базе; отдельный ресурс запроса даёт читать результат конкретного SELECT. |
- PHP вызывает cubrid_connect → брокер CUBRID на своём порту проверяет вход
- cubrid_execute передаёт SQL → сервер выбирает id/title/qty из таблицы
- cubrid_fetch_assoc возвращает очередной массив: title=Кабель USB, qty=6
- PHP формирует HTML → браузер показывает Кабель USB — 6
Брокер — промежуточная служба CUBRID для клиентских запросов; PHP подключается к его порту. Поэтому наличие файла базы или запущенного сервера ещё не доказывает доступность брокера. У папки на диске нет смысла параметра dbname: здесь передаётся имя зарегистрированной базы. Сервер не получает весь PHP-файл — ему отправляется конкретный SQL-запрос.
Первый шаг: получить соединение
$db = cubrid_connect("127.0.0.1", 33165, "phpmanual165", $user, $password);Символ $ начинает имя переменной. $user и $password — ваши настройки входа, заранее прочитанные из закрытой конфигурации; настоящий секрет в коде урока не указан. Имя функции стоит слева от круглых скобок, внутри через запятые перечислены аргументы: адрес, порт брокера, база, логин и секрет. Знак = записывает возвращённый результат в $db; точка с запятой заканчивает инструкцию. Успех даёт ресурс соединения, а не товары. При false читать данные через него нельзя. Полная проверка разобрана в cubrid_connect.
Второй шаг: таблица, запись и чтение
$request = cubrid_execute($db, "CREATE TABLE products (id INT PRIMARY KEY, title VARCHAR(120), qty INT)");
cubrid_close_request($request);
$request = cubrid_execute($db, "INSERT INTO products (id,title,qty) VALUES (1,'Кабель USB',6)");
cubrid_close_request($request);
cubrid_commit($db);Это короткая иллюстрация для пустой отдельной базы с уже успешным $db. CREATE TABLE задаёт структуру; INSERT INTO перечисляет столбцы и соответствующие значения; число 6 не заключено в SQL-кавычки, текст заключён. commit подтверждает изменения в выбранном режиме явной транзакции. В рабочей программе каждый отказ проверяется до использования ресурса, таблица получает уникальное собственное имя, а уборка происходит в finally. Полный первый каталог добавляет две строки и действительно читает их обратно. Не исполняйте этот короткий CREATE поверх существующей рабочей таблицы.
Затем запросы развиваются последовательно: выбор только нужных данных → настройки URL и текст → отказ входа и ошибка SQL. Когда значения начнут приходить из формы или API, переходите к prepare/bind и параметрам каталога. Общие понятия связей и запросов можно сопоставить с работой PHP с базой; native CUBRID остаётся отдельным API со своими результатами функций.
Как самостоятельно запустить примеры
Примеры рассчитаны на конкретный отдельный стенд: PHP 7.4.33 CLI, native cubrid 11.2.0.0002 и CUBRID 11.3.5. Это историческая ветка PHP для разбора данного расширения; PHP сайта не понижается. Наличие PDO_CUBRID не делает доступными функции cubrid_*. Каждая программа из ZIP создаёт собственную таблицу, показывает действительные строки в result.html/result.json и затем удаляет только эту таблицу.
README в ZIP содержит подготовку отдельного сервера, параметры среды и запуск. Брокер размещён в Linux network/IPC namespaces без внешнего сетевого интерфейса; PHP запускается там же. Пароль находится в закрытых переменных окружения. Маркер проверяет выбранный стенд, а SQL дополнительно подтверждает имя базы. Эти предохранители относятся к запуску демонстраций и не заменяют полномочия пользователя приложения.
В уроках автокоммит явно выключен: сохранение подтверждается commit. Подготовка таблицы и данных завершена до изучаемого SELECT; незавершённая работа отменяется перед очисткой. Поэтому закрытие ресурса не изображается как неявная гарантия сохранения. Короткие фрагменты предполагают уже успешные подключения и таблицы; архив содержит целую программу, обработку отказов и понятный результат.
Создать первый каталог и увидеть две сохранённые строки
Небольшому складу нужен экран остатков. Пока вместо всей системы сделаем законченное действие: сохраним два товара в собственной таблице и получим из базы «Кабель USB — 6» и «Предохранитель 10A — 0». Данные будут прочитаны запросом после записи; ноль не исчезнет как якобы пустое значение.
- CREATE TABLE → колонки id / sku / title / category / price_cents / qty / note
- INSERT: USB-165, Кабель USB, 6; INSERT: FUSE-165, Предохранитель 10A, 0
- commit → изменения подтверждены сервером
- SELECT id,title,qty ORDER BY id LIMIT 2 → два массива → понятная таблица
Минимальная запись
$request = cubrid_execute($db, "SELECT id, title, qty FROM products ORDER BY id LIMIT 2");
if ($request === false) { throw new RuntimeException("Запрос не выполнен"); }
while (($row = cubrid_fetch_assoc($request)) !== false) {
if ($row === null) { throw new RuntimeException("Ошибка чтения"); }
echo $row["title"], " — ", $row["qty"], "\n";
}
cubrid_close_request($request);Здесь $db — уже созданное соединение, а products — уже созданная таблица. cubrid_execute получает SQL-текст и возвращает ресурс запроса $request. В SELECT после имени команды перечислены нужные столбцы; FROM задаёт источник, ORDER BY id — порядок, LIMIT 2 — максимум строк. fetch_assoc каждый раз возвращает следующую строку с именованными ключами. $row["title"] берёт одно поле; echo выводит текст. false завершает цикл, а null сигнализирует об ошибке чтения. Полный файл создаёт таблицу со случайным собственным именем; ни чужой products, ни весь каталог он не удаляет.
Что покажет полная программа
| Наблюдение | Результат |
|---|---|
| Добавлено товаров | 2 |
| Строк на экране | 2 |
| Кабель USB, шт. | 6 |
| Предохранитель 10A, шт. | 0 |
| Поля каждой строки | id, title, qty |
| Ноль показан как остаток | да |
<?php
declare(strict_types=1);
require __DIR__.'/lab.php';
$db=null;$owned=$removed=$rows=$checks=$observations=[];
try {
$config=c165Config();$db=c165Connect();$runtime=c165Runtime($db);
$name=c165CreateTable($db,$owned,'catalog');$table=c165Qualified($name);
// These are fixed teaching values, not text from a form.
$inserts=[
"INSERT INTO $table (id,sku,title,category,price_cents,qty,note) VALUES (1,'USB-165','Кабель USB','cables',12900,6,NULL)",
"INSERT INTO $table (id,sku,title,category,price_cents,qty,note) VALUES (2,'FUSE-165','Предохранитель 10A','fuses',4500,0,'')"
];
$inserted=[];
foreach($inserts as $sql) {
$request=cubrid_execute($db,$sql);
if ($request===false) {c165Failure('Товар не записан');}
try {$inserted[]=(int)cubrid_affected_rows($request);} finally {c165Release($request);}
}
c165Commit($db);
$request=cubrid_execute($db,'SELECT id,title,qty FROM '.$table.' ORDER BY id LIMIT 2');
if ($request===false) {c165Failure('Каталог не прочитан');}
try {$raw=c165Rows($request);} finally {c165Release($request);}
$items=[];
foreach($raw as $row) {$items[]=['id'=>(int)$row['id'],'title'=>$row['title'],'qty'=>(int)$row['qty']];}
$expected=[['id'=>1,'title'=>'Кабель USB','qty'=>6],['id'=>2,'title'=>'Предохранитель 10A','qty'=>0]];
$rows=[['Добавлено товаров',array_sum($inserted)],['Строк на экране',count($items)],
['Кабель USB, шт.',$items[0]['qty']],['Предохранитель 10A, шт.',$items[1]['qty']],
['Поля каждой строки',implode(', ',array_keys($items[0]))],['Ноль показан как остаток',$items[1]['qty']===0]];
$checks=['two_inserts'=>$inserted===[1,1],'catalog_read'=>$items===$expected,
'only_needed_fields'=>array_keys($items[0])===['id','title','qty'],'zero_preserved'=>$items[1]['qty']===0,
'request_released'=>$request===null];
$observations=['selected_items'=>$items,'raw_driver_rows'=>$raw,'affected_rows'=>$inserted,
'query_shape'=>'SELECT id,title,qty ORDER BY id LIMIT 2','values_are_fixed_fixture'=>true];
} finally {
if (is_resource($db)) {try {$removed=c165Cleanup($db,$owned);} finally {c165Close($db);}}
}
c165Report('cub165-first-catalog','Создать первый каталог и увидеть две сохранённые строки',$rows,$checks,$observations,$runtime,$owned,$removed);
Ожидаемый результат
Добавлено товаров — 2
Строк на экране — 2
Кабель USB, шт. — 6
Предохранитель 10A, шт. — 0
Поля каждой строки — id, title, qty
Ноль показан как остаток — да
Самостоятельный CLI-пример для отдельной лаборатории CUBRID. В архиве находятся example.php, lab.php и README; создаётся одна собственная таблица, а фактический отчёт сохраняется в HTML и JSON.
HTML с результатом · JSON с данными и наблюдениями.
Ошибки и границы
Числа из native fetch могут приходить строками. Здесь известные INT-поля явно преобразуются в int для таблицы и сравнения; исходные значения сохранены отдельно. Это не универсальное разрешение превращать любую строку в число. SQL NULL внутри строки и false вместо строки имеют разный смысл. Статические INSERT выше содержат только авторские значения. Текст формы нельзя склеивать с таким SQL: дальше используется prepare/bind. close_request освобождает запрос, а disconnect — соединение; это два ресурса, а не две формы одного результата.
Автор вопроса сравнивал экранирование строк в разных PHP-драйверах при построении динамического SQL. Обсуждение на Stack Overflow. Первую таблицу наполняют только фиксированные авторские значения. Как только появляются данные формы, даём отдельный шаг prepare/bind; имена таблиц проходят собственный allowlist и не подменяются маркером значения. Ответы про общую MySQL-подобную обработку кавычек не копируем.
Измените требование
Нужно показывать SKU рядом с названием. Достаточно ли добавить ключ в PHP-массив?
Разбор решения
Добавьте sku в SELECT, затем явно перенесите row["sku"] в модель строки. База передаст нужное поле; PHP не сможет восстановить его из названия. Не заменяйте список полей на SELECT * только ради одного нового столбца.
Получить две доступные позиции, не загружая весь каталог
Для блока «Недорогие товары в наличии» нужны две позиции. Получать все товары, переносить их в большой PHP-массив, фильтровать и сортировать там — лишняя работа и передача данных. В нашем каталоге будет четыре записи, а запрос сразу вернёт клипсу за 900 копеек и изоленту за 5900. Тот же принцип важен при десятках и сотнях тысяч строк.
- Четыре товара: цены 12900 / 4500 / 900 / 5900, остатки 6 / 0 / 20 / 4
- WHERE qty > 0 → предохранитель с нулём не входит в результат
- ORDER BY price_cents,id → клипса, изолента, кабель
- LIMIT 2 + перечень пяти столбцов → в PHP приходят только две нужные строки
Минимальная запись
$request = cubrid_execute($db,
"SELECT id, sku, title, price_cents, qty FROM products " .
"WHERE qty > 0 ORDER BY price_cents, id LIMIT 2"
);Точка между строками склеивает один SQL-текст; это не два запроса. Знак > сравнивает остаток с нулём на сервере. Запятая в ORDER BY добавляет второй критерий: если цены совпадают, порядок определяет уникальный id. LIMIT ограничивает количество возвращаемых строк. Цена хранится целым числом копеек, поэтому 5900 означает 59 рублей; денежную дробь из float здесь не вычисляют.
Что покажет полная программа
| Наблюдение | Результат |
|---|---|
| Товаров в подготовленном каталоге | 4 |
| Получено строк | 2 |
| Первая доступная позиция | Клипса для кабеля |
| Её цена, коп. | 900 |
| Вторая доступная позиция | Изолента |
| Её цена, коп. | 5900 |
| Нулевые остатки не пришли в PHP | да |
<?php
declare(strict_types=1);
require __DIR__.'/lab.php';
$db=null;$owned=$removed=$rows=$checks=$observations=[];
try {
$config=c165Config();$db=c165Connect();$runtime=c165Runtime($db);
$name=c165CreateTable($db,$owned,'screen',[
['id'=>1,'sku'=>'USB-165','title'=>'Кабель USB','category'=>'cables','price_cents'=>12900,'qty'=>6,'note'=>null],
['id'=>2,'sku'=>'FUSE-165','title'=>'Предохранитель 10A','category'=>'fuses','price_cents'=>4500,'qty'=>0,'note'=>''],
['id'=>3,'sku'=>'CLIP-165','title'=>'Клипса для кабеля','category'=>'mounting','price_cents'=>900,'qty'=>20,'note'=>null],
['id'=>4,'sku'=>'TAPE-165','title'=>'Изолента','category'=>'mounting','price_cents'=>5900,'qty'=>4,'note'=>null]
]);$table=c165Qualified($name);
$sql='SELECT id,sku,title,price_cents,qty FROM '.$table.' WHERE qty > 0 ORDER BY price_cents,id LIMIT 2';
$request=cubrid_execute($db,$sql);
if ($request===false) {c165Failure('Выборка экрана не выполнена');}
try {$raw=c165Rows($request);} finally {c165Release($request);}
$items=[];
foreach($raw as $row) {$items[]=['id'=>(int)$row['id'],'sku'=>$row['sku'],'title'=>$row['title'],
'price_cents'=>(int)$row['price_cents'],'qty'=>(int)$row['qty']];}
$rows=[['Товаров в подготовленном каталоге',4],['Получено строк',count($items)],
['Первая доступная позиция',$items[0]['title']],['Её цена, коп.',$items[0]['price_cents']],
['Вторая доступная позиция',$items[1]['title']],['Её цена, коп.',$items[1]['price_cents']],
['Нулевые остатки не пришли в PHP',count(array_filter($items,static function(array $v):bool{return $v['qty']<=0;}))===0]];
$checks=['two_rows'=>count($items)===2,'correct_order'=>array_column($items,'id')===[3,4],
'correct_values'=>$items[0]['price_cents']===900&&$items[1]['price_cents']===5900&&$items[0]['qty']===20&&$items[1]['qty']===4,
'selected_projection'=>array_keys($items[0])===['id','sku','title','price_cents','qty'],
'request_released'=>$request===null];
$observations=['selected_items'=>$items,'raw_driver_rows'=>$raw,'sql_clause_order'=>['SELECT нужные поля','WHERE qty > 0','ORDER BY price_cents,id','LIMIT 2'],
'php_sort_used'=>false,'php_filter_used_to_build_screen'=>false,'fixture_rows'=>4];
} finally {
if (is_resource($db)) {try {$removed=c165Cleanup($db,$owned);} finally {c165Close($db);}}
}
c165Report('cub165-screen-select','Получить две доступные позиции, не загружая весь каталог',$rows,$checks,$observations,$runtime,$owned,$removed);
Ожидаемый результат
Товаров в подготовленном каталоге — 4
Получено строк — 2
Первая доступная позиция — Клипса для кабеля
Её цена, коп. — 900
Вторая доступная позиция — Изолента
Её цена, коп. — 5900
Нулевые остатки не пришли в PHP — да
Самостоятельный CLI-пример для отдельной лаборатории CUBRID. В архиве находятся example.php, lab.php и README; создаётся одна собственная таблица, а фактический отчёт сохраняется в HTML и JSON.
HTML с результатом · JSON с данными и наблюдениями.
Ошибки и границы
SELECT * выбирает все столбцы, а не сам по себе все строки. Все строки получаются из-за отсутствия подходящих условий и ограничения. Для конкретного экрана нужно решить обе задачи: какие поля и какие записи. Индекс может помочь серверу, но четыре учебные строки не доказывают план или ускорение на вашей базе. Для больших таблиц изучают реальный план, распределение данных и нужный индекс. Проверка результата через array_filter в checks только обнаруживает нарушение условия; она не строит и не сортирует экран.
Автор обсуждения планировал таблицы с большим числом столбцов и индексов и спрашивал о цене такой структуры и запросов. Обсуждение на Stack Overflow. Делаем проекцию нужных полей и ограниченный результат под конкретный экран; объясняем, что цена большого SELECT и качество индексов требуют реального плана. Старые обещания производительности и пределы из ответа не выдаём за современный контракт.
Измените требование
У двух товаров одинаковая цена. Как сохранить однозначный порядок и получить следующую страницу?
Разбор решения
Не убирайте id из ORDER BY. Следующая глава показывает ограниченные страницы с параметрами и полным порядком. Для растущей таблицы дополнительно сравните offset и запрос после последней пары (price_cents,id), а не храните весь отсортированный каталог в памяти PHP.
Задать URL подключения и прочитать русский текст без потерь
В настройках интеграции удобно хранить адрес брокера, имя базы и время ожидания одной строкой. Но строка подключения не должна превращаться в опубликованный пароль. Создадим URL с отдельными реквизитами и проверим настоящую запись «Кабель Север / Для склада №2». Простого сообщения «подключено» недостаточно, чтобы увидеть, правильно ли прошёл текст.
- URL задаёт broker 33165 / phpmanual165 / login_timeout 3000 мс
- user и password переданы отдельными аргументами → новый ресурс соединения
- UTF-8 название и примечание → INSERT → commit
- SELECT одного товара → те же строки → HTML UTF-8, URL с секретом не публикуется
Минимальная запись
$url = "CUBRID:127.0.0.1:33165:phpmanual165:::?login_timeout=3000";
$db = cubrid_connect_with_url($url, $user, $password, true);
if ($db === false) { throw new RuntimeException("Нет подключения"); }URL здесь — формат драйвера CUBRID, не адрес веб-страницы. Двоеточия разделяют host, port, database, user и password; пустые позиции остаются на месте, потому что логин и секрет переданы следующими аргументами. true просит отдельное новое соединение. 3000 измеряется в миллисекундах. Кодировка не возникает из HTML-тега: отдельная база и клиент должны согласованно работать с UTF-8, а отчёт отдельно объявляет UTF-8 для браузера.
Что покажет полная программа
| Наблюдение | Результат |
|---|---|
| Соединение создано через URL | да |
| SKU | NORTH-165 |
| Название | Кабель Север |
| Примечание | Для склада №2 |
| Название вернулось без потерь | да |
| Примечание вернулось без потерь | да |
| Реквизиты отсутствуют в отчёте | да |
<?php
declare(strict_types=1);
require __DIR__.'/lab.php';
$db=null;$owned=$removed=$rows=$checks=$observations=[];
try {
$config=c165Config();$db=c165Connect();$runtime=c165Runtime($db);
c165Close($db);
$address='CUBRID:'.$config['host'].':'.$config['port'].':'.$config['database'].':::?login_timeout=3000';
$call=c165Capture(static function() use ($address,$config) {
return cubrid_connect_with_url($address,$config['user'],$config['password'],true);
});
if (!is_resource($call['value']) || $call['warning']) {c165Failure('Подключение по URL не создано',$call);}
$db=$call['value'];unset($call);
if (cubrid_set_autocommit($db,false)!==true) {c165Failure('Не задан режим транзакций');}
$runtime=c165Runtime($db);
$name=c165CreateTable($db,$owned,'url_text',[
['id'=>1,'sku'=>'NORTH-165','title'=>'Кабель Север','category'=>'cables','price_cents'=>12900,'qty'=>6,'note'=>'Для склада №2'],
['id'=>2,'sku'=>'LABEL-165','title'=>'Бирка','category'=>'labels','price_cents'=>300,'qty'=>20,'note'=>'']
]);$table=c165Qualified($name);
$request=cubrid_execute($db,'SELECT sku,title,note FROM '.$table.' WHERE id = 1 LIMIT 1');
if ($request===false) {c165Failure('Русский текст не прочитан');}
try {$actual=c165Rows($request);} finally {c165Release($request);}
$row=$actual[0];$title='Кабель Север';$note='Для склада №2';
$rows=[['Соединение создано через URL',is_resource($db)],['SKU',$row['sku']],['Название',$row['title']],
['Примечание',$row['note']],['Название вернулось без потерь',$row['title']===$title],
['Примечание вернулось без потерь',$row['note']===$note],['Реквизиты отсутствуют в отчёте',true]];
$checks=['url_connection'=>is_resource($db),'exact_row'=>$actual===[['sku'=>'NORTH-165','title'=>$title,'note'=>$note]],
'utf8_valid'=>preg_match('//u',$row['title'].$row['note'])===1,'one_row'=>count($actual)===1,
'request_released'=>$request===null];
$observations=['selected_item'=>$row,'url_shape'=>'CUBRID:<host>:<broker_port>:<database>:::?login_timeout=3000',
'credentials_supplied_separately'=>true,'forced_new_link'=>true,'login_timeout_ms'=>3000,
'title_bytes'=>strlen($row['title']),'note_bytes'=>strlen($row['note']),'charset'=>$runtime['charset']];
} finally {
if (is_resource($db)) {try {$removed=c165Cleanup($db,$owned);} finally {c165Close($db);}}
}
c165Report('cub165-url-connection','Задать URL подключения и прочитать русский текст без потерь',$rows,$checks,$observations,$runtime,$owned,$removed);
Ожидаемый результат
Соединение создано через URL — да
SKU — NORTH-165
Название — Кабель Север
Примечание — Для склада №2
Название вернулось без потерь — да
Примечание вернулось без потерь — да
Реквизиты отсутствуют в отчёте — да
Самостоятельный CLI-пример для отдельной лаборатории CUBRID. В архиве находятся example.php, lab.php и README; создаётся одна собственная таблица, а фактический отчёт сохраняется в HTML и JSON.
HTML с результатом · JSON с данными и наблюдениями.
Ошибки и границы
В пароль, встроенный в URL, нельзя бездумно вставлять разделители : и ?. Отдельные аргументы решают именно эту неоднозначность; URL с реквизитами нельзя писать в журнал или HTML. login_timeout ограничивает вход, а не полное время всей PHP-программы. query_timeout относится к SQL и не доказывает, что команда ничего не успела изменить. Время 3000 мс не является гарантией завершить каждую сетевую ситуацию ровно через три секунды; процесс запуска лаборатории дополнительно имеет общий предел.
Измените требование
Название содержит 12 русских букв и пробелы. Почему strlen не обязан совпасть с количеством букв?
Разбор решения
strlen считает байты PHP-строки. В UTF-8 русская буква обычно занимает несколько байтов, а пробел — один. Для ограничения видимых символов нужен подходящий Unicode-инструмент; для проверки передачи без потерь сравнивайте исходную и прочитанную строки. Не обрезайте строку посреди UTF-8-последовательности по произвольному числу байтов.
Отличить отказ входа от ошибки SQL и восстановить чтение
Страница пишет «нет товаров», но на самом деле приложение не вошло в базу или запросило несуществующий столбец. Это разные неисправности, и обе нельзя маскировать пустым массивом. В примере неверный секрет даст сохранённую диагностику; правильный вход затем сработает. Отдельная ошибочная SQL-команда также будет распознана, а после исправления экран покажет «Переходник — 5».
- Вход с неверным секретом → false → сразу code / facility / message_present
- Правильные настройки → новый ресурс соединения → собственный товар ADAPTER-165
- SELECT отсутствующего столбца → отдельная SQL-ошибка → сохранить диагностику
- Rollback текущей неудачной работы → корректный SELECT → Переходник, 5
Минимальная запись
$db = cubrid_connect_with_url($url, $user, $password, true);
if ($db === false) {
$error = ["code" => cubrid_error_code(),
"facility" => cubrid_error_code_facility(),
"message" => cubrid_error_msg()];
// Сохранить в закрытый журнал; посетителю не выводить реквизиты и детали.
}Проверка === false сравнивает именно отказ, а не любое «пустое» значение. Массив $error сохраняет три связанные части диагностики до следующего обращения к драйверу. code — номер причины, facility — слой CUBRID, где она зарегистрирована, message — пояснение. В полной программе предупреждение также перехватывается, а публичный отчёт получает только признак наличия текста. Правильный запрос выполняется явно после разбора отказа; автоматического бесконечного переподключения нет.
Что покажет полная программа
| Наблюдение | Результат |
|---|---|
| Неверный секрет отклонён | да |
| Диагностика входа сохранена | да |
| Правильные реквизиты дали подключение | да |
| Ошибка столбца не стала пустым каталогом | да |
| После исправления прочитан товар | Переходник |
| Его остаток, шт. | 5 |
<?php
declare(strict_types=1);
require __DIR__.'/lab.php';
$db=null;$owned=$removed=$rows=$checks=$observations=[];
try {
$config=c165Config();
$address='CUBRID:'.$config['host'].':'.$config['port'].':'.$config['database'].':::?login_timeout=3000';
$wrongPassword=($config['password'][0]==='x'?'y':'x').substr($config['password'],1);
$wrong=c165Capture(static function() use ($address,$config,$wrongPassword) {
return cubrid_connect_with_url($address,$config['user'],$wrongPassword,true);
});
$authFailure=['connected'=>is_resource($wrong['value']),'code'=>$wrong['code'],'facility'=>$wrong['facility'],
'warning'=>$wrong['warning'],'message_present'=>$wrong['message_present']];
if (is_resource($wrong['value'])) {cubrid_disconnect($wrong['value']);}$wrong['value']=null;unset($wrong);
if ($authFailure['connected']) {throw new RuntimeException('Контрольный неверный секрет неожиданно принят.');}
$db=c165Connect();$runtime=c165Runtime($db);
$name=c165CreateTable($db,$owned,'recovery',[
['id'=>1,'sku'=>'ADAPTER-165','title'=>'Переходник','category'=>'adapters','price_cents'=>7900,'qty'=>5,'note'=>null]
]);$table=c165Qualified($name);
// A distinct controlled SQL failure: the connection exists, but this column does not.
$badQuery=c165Capture(static function() use ($db,$table) {return cubrid_execute($db,'SELECT missing_column_165 FROM '.$table.' LIMIT 1');});
$queryFailure=['request_created'=>is_resource($badQuery['value']),'code'=>$badQuery['code'],'facility'=>$badQuery['facility'],
'warning'=>$badQuery['warning'],'message_present'=>$badQuery['message_present']];
if (is_resource($badQuery['value'])) {cubrid_close_request($badQuery['value']);}$badQuery['value']=null;unset($badQuery);
c165Rollback($db);
$actual=c165Read($db,'SELECT sku,title,qty FROM '.$table.' WHERE id = 1 LIMIT 1');
$rows=[['Неверный секрет отклонён',!$authFailure['connected']],['Диагностика входа сохранена',$authFailure['code']!==0&&$authFailure['message_present']],
['Правильные реквизиты дали подключение',is_resource($db)],['Ошибка столбца не стала пустым каталогом',!$queryFailure['request_created']],
['После исправления прочитан товар',$actual[0]['title']],['Его остаток, шт.',(int)$actual[0]['qty']]];
$checks=['auth_rejected'=>!$authFailure['connected']&&$authFailure['code']!==0&&$authFailure['message_present'],
'query_rejected'=>!$queryFailure['request_created']&&$queryFailure['code']!==0&&$queryFailure['message_present'],
'fresh_connection'=>is_resource($db),'catalog_recovered'=>count($actual)===1&&$actual[0]['sku']==='ADAPTER-165'&&$actual[0]['title']==='Переходник'&&(int)$actual[0]['qty']===5,
'diagnostics_distinguished'=>$authFailure['code']!==$queryFailure['code']];
$observations=['authentication_failure'=>$authFailure,'sql_failure'=>$queryFailure,'recovered_row'=>$actual[0],
'raw_error_text_published'=>false,'password_published'=>false,'automatic_retries'=>0];
} finally {
if (is_resource($db)) {try {$removed=c165Cleanup($db,$owned);} finally {c165Close($db);}}
}
c165Report('cub165-connection-recovery','Отличить отказ входа от ошибки SQL и восстановить чтение',$rows,$checks,$observations,$runtime,$owned,$removed);
Ожидаемый результат
Неверный секрет отклонён — да
Диагностика входа сохранена — да
Правильные реквизиты дали подключение — да
Ошибка столбца не стала пустым каталогом — да
После исправления прочитан товар — Переходник
Его остаток, шт. — 5
Самостоятельный CLI-пример для отдельной лаборатории CUBRID. В архиве находятся example.php, lab.php и README; создаётся одна собственная таблица, а фактический отчёт сохраняется в HTML и JSON.
HTML с результатом · JSON с данными и наблюдениями.
Ошибки и границы
Не печатайте исходное сообщение драйвера каждому посетителю: там могут оказаться имена базы, таблиц, адреса и другие детали. Отрицательный code не универсален между версиями и разными отказами, поэтому таблица урока не обещает один номер на все случаи. Повторный запрос не должен стереть ещё не сохранённую диагностику. Ни неверный пароль, ни синтаксическая ошибка SQL не исправляются увеличением LIMIT. После timeout записи нельзя автоматически повторять INSERT без разбора возможного результата.
В вопросе CUBRID и расширение уже были установлены, но PHP в CI не мог подключиться к demodb; проверялись порты и окружение. Обсуждение на Stack Overflow. Разделяем загрузку расширения, CCI, broker, имя базы, адрес и вход. Пример сохраняет реальный этап отказа и затем выполняет настоящий SELECT. Старые PPA, команды PHP5 и чужую конфигурацию Travis не переносим в новый стенд.
Измените требование
Пользователь действительно ничего не нашёл по фильтру. Как отличить это от нашего ошибочного SELECT?
Разбор решения
Успешный SELECT создаёт ресурс запроса. Если первая fetch_assoc возвращает false без ошибки, выборка закончилась без строк. Ошибка execute даёт false вместо запроса; ошибка fetch даёт null вместо массива. Обрабатывайте эти этапы отдельно и показывайте «ничего не найдено» только для успешной пустой выборки.
Справочник соединения и диагностики
| Задача | Функция |
|---|---|
| Открыть соединение с нужной базой через broker. | cubrid_connect |
| Передать адрес, базу и свойства входа в URL. | cubrid_connect_with_url |
| Закрыть выбранное соединение и его оставшиеся запросы. | cubrid_disconnect |
| Сохранить номер последнего отказа CUBRID API. | cubrid_error_code |
| Прочитать пояснение последнего отказа для диагностики. | cubrid_error_msg |
| Определить слой последней ошибки: DBMS, CAS, CCI или клиент. | cubrid_error_code_facility |
resource|false в карточке обозначает возможные результаты документации. Это не объявление PHP-функции с union type для копирования в PHP 7.4; resource вообще не служит пользовательским type hint. Полные программы используют совместимый синтаксис.
Дальше: значения из формы и безопасное изменение остатка
Теперь понятно, где заканчивается подключение и начинается SQL, как получить конкретный экран и не скрыть отказ пустым списком. Следующая глава — параметры каталога, NULL, условное списание и страницы результатов. Она показывает cubrid_prepare, cubrid_bind и различие двух форм cubrid_execute. Эти две главы — начало ветки CUBRID, а не заявление о готовности всего API.
Функции и методы этой темы
Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.
cubrid_connectОткрыть соединение с нужной базой через broker.
PECL CUBRID >= 8.3.1; лаборатория PHP 7.4.33 · cubrid
cubrid_connect(string $host, int $port, string $dbname, string $userid = ?, string $passwd = ?, bool $new_link = false): resource|falseЧтобы экран получил товары, сначала нужен доступ к правильной базе через брокер. cubrid_connect создаёт непостоянное соединение и возвращает его ресурс. Получение ресурса ещё не означает, что таблица существует или SELECT уже выполнен.
| Аргумент | Что передать |
|---|---|
| host: string | Имя или IP узла с broker/CAS. В отдельном стенде — 127.0.0.1 внутри его namespace. |
| port: int | Порт брокера BROKER_PORT из cubrid_broker.conf. 33165 — настройка нашего стенда, не обязательный порт CUBRID. |
| dbname: string | Имя зарегистрированной базы, например phpmanual165; не имя SQL-таблицы и не путь файла. |
| userid: string, необязательно | Логин базы. Manual указывает стандартного public; закреплённый драйвер берёт отсутствие аргумента из cubrid.default_userid. Для приложения выбирают явного ограниченного пользователя. |
| passwd: string, необязательно | Секрет выбранного пользователя. Отсутствие использует cubrid.default_passwd; типовая пустая настройка не является рекомендацией оставлять пароль пустым. |
| new_link: bool = false | false допускает возврат ранее открытого соединения с теми же аргументами. true требует новый link. Это не обещание нового процесса PHP и не настройка persistent pool. |
Результат: ресурс соединения при успехе, false при невозможности подключиться. Проверяйте === false и немедленно сохраняйте диагностику. Адрес, брокер, имя базы, права, секрет и библиотека CCI — разные возможные причины отказа. Настройку соединения нельзя выводить целиком пользователю, особенно с паролем.
1. Открыть каталог для одного запроса
$db = cubrid_connect($host, $brokerPort, $database, $user, $password);
if ($db === false) { throw new RuntimeException("База недоступна"); }
// Теперь можно выполнить SELECT и получить ресурс запроса.В полном первом каталоге после этого создаются два товара и выводятся количества 6 и 0. Функция соединения не возвращает эти строки напрямую; между соединением и HTML стоят SQL и fetch. Для чтения нужны только разрешённые приложению таблицы, а dba в архиве используется исключительно в отдельном стенде для собственной временной таблицы.
2. Отдельный link для независимой работы в том же процессе
$second = cubrid_connect($host, $brokerPort, $database, $user, $password, true);
if ($second === false) { throw new RuntimeException("Второе соединение не создано"); }
try { /* ограниченный запрос этой операции */ }
finally { cubrid_disconnect($second); }Флаг имеет смысл, когда нельзя случайно разделить состояние прежнего link: например, явную транзакцию предыдущей операции. В восстановлении после отказа используются явно новые соединения с известными настройками. Это не программа распределённых транзакций и не доказательство поведения постоянного подключения; для нового процесса нужна отдельная граница исполнения.
В исходнике 11.2.0.0002 парсер также принимает седьмой строковый аргумент attr, отсутствующий в официальной шестипараметровой записи. Мы не превращаем это частное расширение исходника в переносимый контракт и не используем его в программах. Документированные свойства соединения показаны через cubrid_connect_with_url. Большие строки и неоднозначные разделители не надо подбирать методом проб; для сложного секрета отдельные аргументы URL-варианта яснее.
Функции доступны при загруженном native-расширении cubrid. Официальные отметки PECL ниже описывают историю появления API, а не совместимость DLL/so с любым современным PHP. Для этой главы выбран PHP 7.4.33 и модуль 11.2.0.0002; отдельную сборку не подставляют в PHP 8 и не используют для понижения версии сайта. Не называйте номер PECL версией языка PHP. Ошибки параметров вызова тоже могут сопровождаться PHP-предупреждением; корректный ресурс проверяют до последующих операций.
Связанные действия: выполнить SQL, закрыть link, сохранить код отказа.
cubrid_connect_with_urlПередать адрес, базу и свойства входа в URL.
PECL CUBRID >= 8.3.1; лаборатория PHP 7.4.33 · cubrid
cubrid_connect_with_url(string $conn_url, string $userid = ?, string $passwd = ?, bool $new_link = false): resource|falseКонфигурации интеграции бывает нужна строка с адресом брокера, именем базы и ограничением ожидания. cubrid_connect_with_url разбирает специальный URL CUBRID. Он не скачивает веб-страницу и не выполняет переданный SQL.
| Аргумент | Контракт |
|---|---|
| conn_url: string | Строка CUBRID:host:port:database:user:password:?properties. Пустые позиции сохраняют двоеточия. В краткой grammar PHP Manual порт пропущен, но официальные примеры и фактический формат его включают. |
| userid: string, необязательно | Отдельное имя пользователя; позволяет не помещать логин в URL. При отсутствии реквизитов применяется PUBLIC. |
| passwd: string, необязательно | Отдельный секрет. Это необходимо, если пароль содержит разделители : или ?. Не подменяйте значение произвольным URL-encoding без контракта драйвера. |
| new_link: bool = false | При false одинаковые аргументы могут дать уже открытый ресурс; true требует новый. |
| Результат | Ресурс соединения или false. Дальше отдельно выполняется SQL; одного успешного connect недостаточно для проверки текста и данных. |
| Свойство официального URL | Поведение и границы |
|---|---|
| alhosts=host:port,host:port | Брокеры резервных серверов для HA/failover, проверяемые в заданном порядке. Список не создаёт репликацию и не превращает разные базы в одну. |
| rctime=seconds | Интервал попыток вернуться к активному брокеру после отказа; в Manual default 600 секунд. При failover завершается транзакция; состояние старого link нельзя считать сохранённым. |
| login_timeout=milliseconds | Предел ожидания входа; default 0 означает отсутствие этого ограничения. В демонстрации 3000 мс. |
| query_timeout=milliseconds | Предел запроса, по которому отправляется отмена. Запрос мог успеть выполниться; сообщение отмены не доказывает отсутствия изменений. |
| disconnect_on_query_timeout=true|false | Определяет поведение возврата ошибки при query timeout; default false. Это часть контракта клиента, а не универсальный откат бизнес-действия. |
1. Вход с ограниченным ожиданием и отдельным секретом
$url = "CUBRID:127.0.0.1:33165:phpmanual165:::?login_timeout=3000";
$db = cubrid_connect_with_url($url, $user, $password, true);В рабочем сценарии URL после входа сохраняется и читается русский товар. Публичный результат показывает форму URL с placeholders, а не реальные реквизиты. Сравнение строк проверяет полезное действие; echo "connected" не обнаружило бы испорченное название.
2. Настроенный переход на резервный брокер
$url = "CUBRID:primary.example:33000:catalog:::?" .
"alhosts=standby.example:33000&rctime=60&login_timeout=3000";
$db = cubrid_connect_with_url($url, $user, $password);Это контекстная запись для уже настроенного HA-кластера, не запускаемый failover-тест нашей одиночной лаборатории. Имя primary.example и standby.example обозначают ваши реальные узлы после настройки. Резервирование требует доступной реплики, согласованных данных и политики повторов. Разбор входа и SQL-ошибки показывает базовую диагностику, но не выдаётся за проверку переключения кластера.
Функции доступны при загруженном native-расширении cubrid. Официальные отметки PECL ниже описывают историю появления API, а не совместимость DLL/so с любым современным PHP. Для этой главы выбран PHP 7.4.33 и модуль 11.2.0.0002; отдельную сборку не подставляют в PHP 8 и не используют для понижения версии сайта. Не называйте номер PECL версией языка PHP. Ошибки параметров вызова тоже могут сопровождаться PHP-предупреждением; корректный ресурс проверяют до последующих операций.
Следующий шаг: где сохранить пояснение отказа и как закрыть соединение.
cubrid_disconnectЗакрыть выбранное соединение и его оставшиеся запросы.
PECL CUBRID >= 8.3.0; лаборатория PHP 7.4.33 · cubrid
cubrid_disconnect(resource $conn_identifier = ?): boolКогда отчёт уже получен, процессу больше не нужен доступ к базе. cubrid_disconnect закрывает соединение и относящиеся к нему ещё не закрытые request handles. Результирующая HTML-таблица уже является обычными данными PHP; ей не требуется держать ресурс базы открытым.
| Параметр / результат | Смысл |
|---|---|
| conn_identifier: resource, необязательно | Открытый link. Закреплённый драйвер реализует disconnect как alias cubrid_close; при отсутствии аргумента используется текущий default_link. В нескольких соединениях передавайте ресурс явно. |
| bool | Официальный контракт: true при успехе, false при отказе. Неверный/уже закрытый ресурс не следует считать успешной идемпотентной операцией; PHP также может предупредить о неправильном аргументе. |
| Срок жизни | После успешного закрытия прежний link и его незакрытые запросы использовать нельзя. Переменной присваивают null, чтобы последующий код не принял старое значение за рабочее подключение. |
1. Освободить ресурсы после чтения экрана
try {
// Выполнить ограниченный SELECT и собрать обычный массив строк.
} finally {
cubrid_close_request($request);
cubrid_disconnect($db);
$request = null;
$db = null;
}Фрагмент предполагает, что оба ресурса успешно созданы. Полные каталог и выборка экрана проверяют ресурсы до освобождения и дают результату дожить до HTML. Отдельный close_request освобождает запрос сразу после чтения; disconnect завершает соединение в конце.
2. Явно закончить изменения, затем закрыть link
try {
// Проверенные INSERT/UPDATE в режиме autocommit off.
if (!cubrid_commit($db)) { throw new RuntimeException("Commit не выполнен"); }
} finally {
cubrid_disconnect($db);
$db = null;
}Закрытие не подменяет решение «сохранить или отменить». При неудачной записи в прикладном коде нужна явная rollback-ветвь и её проверка, а не допущение о судьбе данных после disconnect. В восстановлении SQL-чтения текущая неудачная работа явно отменяется; собственная таблица очищается отдельно. Более содержательные изменения остатков находятся в параметризованном каталоге.
Функции доступны при загруженном native-расширении cubrid. Официальные отметки PECL ниже описывают историю появления API, а не совместимость DLL/so с любым современным PHP. Для этой главы выбран PHP 7.4.33 и модуль 11.2.0.0002; отдельную сборку не подставляют в PHP 8 и не используют для понижения версии сайта. Не называйте номер PECL версией языка PHP. Ошибки параметров вызова тоже могут сопровождаться PHP-предупреждением; корректный ресурс проверяют до последующих операций.
Не закрывайте случайное default-подключение, если в программе несколько link. Для одноразового ресурса эта функция не является гарантией поведения cubrid_pconnect: постоянные подключения требуют отдельного анализа. Карточка запросов: cubrid_close_request.
cubrid_error_codeСохранить номер последнего отказа CUBRID API.
PECL CUBRID >= 8.3.0; лаборатория PHP 7.4.33 · cubrid
cubrid_error_code(): intПри отказе нужен устойчивый номер, который можно сохранить в журнале и сопоставить с конкретной версией драйвера. cubrid_error_code возвращает последний код ошибки CUBRID API; вызов не принимает ни ресурс, ни номер запроса.
| Часть контракта | Разбор |
|---|---|
| Параметры | Нет. Пишите cubrid_error_code(), а не cubrid_error_code($db). |
| int | Код последней ошибки; 0, если ошибки в текущем сохранённом состоянии нет. Это не количество выбранных или изменённых строк. |
| Момент чтения | Сразу после отказа API. Следующая операция может заново инициализировать recent_error; сохраните код, facility и текст в обычный массив. |
1. Отдельно зарегистрировать отказ входа
if ($db === false) {
$failure = ["stage" => "connect", "code" => cubrid_error_code(),
"facility" => cubrid_error_code_facility()];
}В контролируемом восстановлении это запись authentication_failure. Номер не выводится как пароль и не превращается в «нет товаров». Функция code не лечит вход: необходимо исправить причину настройки или реквизитов.
2. Отличить ошибку SQL от успешной пустой выборки
$request = cubrid_execute($db, $sql);
if ($request === false) {
$failure = ["stage" => "query", "code" => cubrid_error_code()];
// Не выдавать этот отказ за пустой список товаров.
}Тот же полный сценарий намеренно использует отсутствующий столбец, сохраняет отдельный sql_failure, а затем читает Переходник — 5 корректным запросом. Сравнивать код с количеством строк бессмысленно; пустой успешный SELECT определяется чтением результата. fetch_assoc возвращает отдельные сигналы для строки, конца и ошибки.
Функции доступны при загруженном native-расширении cubrid. Официальные отметки PECL ниже описывают историю появления API, а не совместимость DLL/so с любым современным PHP. Для этой главы выбран PHP 7.4.33 и модуль 11.2.0.0002; отдельную сборку не подставляют в PHP 8 и не используют для понижения версии сайта. Не называйте номер PECL версией языка PHP. Ошибки параметров вызова тоже могут сопровождаться PHP-предупреждением; корректный ресурс проверяют до последующих операций.
Не фиксируйте старые номера из примеров PHP.net как обязательные для всех серверов и причин. Сохранённый код связывают с этапом, runtime и уровнем ошибки. Для текста есть cubrid_error_msg.
cubrid_error_msgПрочитать пояснение последнего отказа для диагностики.
PECL CUBRID >= 8.3.0; лаборатория PHP 7.4.33 · cubrid
cubrid_error_msg(): stringТекст ошибки помогает разработчику понять, какой объект, запрос или настройка вызвали отказ. cubrid_error_msg возвращает пояснение сохранённой ошибки CUBRID API без аргументов. Это диагностический текст, который может содержать детали вашей инфраструктуры.
| Часть контракта | Разбор |
|---|---|
| Параметры | Нет. У этой функции нет выбора подключения аргументом. |
| string | Сообщение последнего отказа. В закреплённом драйвере читается recent_error.msg; пустая строка соответствует отсутствию сохранённого текста. |
| Проверка успеха | Сначала проверяют результат самой операции. Наличие или отсутствие текста не заменяет проверку false/null конкретной функции. |
| Обработка | Сохранить сразу, затем записать в закрытый журнал с контекстом. Публичному пользователю дать понятное описание без реквизитов и внутренней SQL-структуры. |
1. Диагностика неправильно настроенной интеграции
if ($db === false) {
$code = cubrid_error_code();
$message = cubrid_error_msg();
$publicStatus = "Подключение к каталогу не выполнено";
// $message предназначен для закрытой диагностики, не HTML посетителя.
}В программе отказа входа вместо исходного текста в открытый result.json включён message_present. Это позволяет показать, что диагностика была получена, не публикуя секретные подробности. Полный приватный журнал реального приложения должен иметь свою политику доступа и срок хранения.
2. Сохранить причину до следующей SQL-команды
$request = cubrid_execute($db, $sql);
if ($request === false) {
$details = ["code" => cubrid_error_code(),
"facility" => cubrid_error_code_facility(),
"message" => cubrid_error_msg()];
// Теперь можно выполнять rollback и отдельное исправленное действие.
}Это защищает сообщение от перезаписи успешным служебным запросом. В том же сценарии SQL-отказ и исправленный SELECT существуют отдельно. Нельзя анализировать message только после успешной повторной выборки и утверждать, что прежней ошибки не было.
Функции доступны при загруженном native-расширении cubrid. Официальные отметки PECL ниже описывают историю появления API, а не совместимость DLL/so с любым современным PHP. Для этой главы выбран PHP 7.4.33 и модуль 11.2.0.0002; отдельную сборку не подставляют в PHP 8 и не используют для понижения версии сайта. Не называйте номер PECL версией языка PHP. Ошибки параметров вызова тоже могут сопровождаться PHP-предупреждением; корректный ресурс проверяют до последующих операций.
Не разрабатывайте бизнес-правила на поиске одного английского слова в сообщении: версии и формулировки меняются. Для классификации сначала используйте этап, код и facility, а текст — для объяснения и поиска причины. См. cubrid_error_code и cubrid_error_code_facility.
cubrid_error_code_facilityОпределить слой последней ошибки: DBMS, CAS, CCI или клиент.
PECL CUBRID >= 8.3.0; лаборатория PHP 7.4.33 · cubrid
cubrid_error_code_facility(): intОдин отказ может возникнуть в сервере базы, другом компоненте подключения или PHP-модуле. cubrid_error_code_facility сообщает слой, где зарегистрирована ошибка. Это помогает направить диагностику, но само по себе не доказывает, что виноват именно сетевой администратор или сервер.
| Контракт / константа | Значение для диагностики |
|---|---|
| Параметры и результат | Нет аргументов; возвращается int facility последней ошибки. Читайте вместе с code и msg сразу после отказа. |
| CUBRID_FACILITY_DBMS | Ошибка СУБД: например, сервер не принимает SQL либо объект не существует. |
| CUBRID_FACILITY_CAS | Уровень CAS брокера. Проверяются состояние посредника и соответствующая диагностика, а не только PHP-синтаксис. |
| CUBRID_FACILITY_CCI | Уровень клиентского интерфейса CCI, на котором построено PHP-расширение. |
| CUBRID_FACILITY_CLIENT | Сам PHP-модуль CUBRID: например, неправильное использование его API. |
1. Отчёт интеграции с указанием слоя отказа
if ($db === false) {
$diagnostic = ["operation" => "catalog-connect",
"facility" => cubrid_error_code_facility(),
"code" => cubrid_error_code()];
}В полном восстановлении вход и SQL имеют отдельные records. Facility не подменяет код: разные причины могут относиться к одному слою, а доступность брокера не гарантирует успешного запроса к таблице.
2. Добавить понятное имя слоя без магических чисел
$labels = [CUBRID_FACILITY_DBMS => "сервер базы",
CUBRID_FACILITY_CAS => "CAS брокера",
CUBRID_FACILITY_CCI => "клиент CCI",
CUBRID_FACILITY_CLIENT => "PHP-модуль"];
$level = cubrid_error_code_facility();
$label = isset($labels[$level]) ? $labels[$level] : "нет известной категории";Так можно дополнить закрытый журнал импорта или диагностику каталога. Константы читаются понятнее чисел 1/2/3/4 и принадлежат установленному расширению. Не показывайте отдельный facility успешного запроса как «ошибку нулевого уровня»: сначала нужен установленный отказ самой операции. Переход к параметрам запроса добавляет ещё один важный этап — подготовку и привязку значений.
Функции доступны при загруженном native-расширении cubrid. Официальные отметки PECL ниже описывают историю появления API, а не совместимость DLL/so с любым современным PHP. Для этой главы выбран PHP 7.4.33 и модуль 11.2.0.0002; отдельную сборку не подставляют в PHP 8 и не используют для понижения версии сайта. Не называйте номер PECL версией языка PHP. Ошибки параметров вызова тоже могут сопровождаться PHP-предупреждением; корректный ресурс проверяют до последующих операций.
Связанные инструменты: точный код и поясняющий текст. Эта классификация не является универсальным кодом HTTP и не должна без преобразования становиться статусом ответа сайта.
Источники и обсуждения
- PHP Manual — cubrid_connect
- PHP Manual — cubrid_connect_with_url
- PHP Manual — cubrid_disconnect
- PHP Manual — cubrid_error_code
- PHP Manual — cubrid_error_msg
- PHP Manual — cubrid_error_code_facility
- PHP Manual — cubrid_execute
- PHP Manual — cubrid_fetch_assoc
- PHP Manual — cubrid_close_request
- CUBRID PHP 11.2.0.0002 — исходник native PHP7
- CUBRID — устройство PHP/CCI драйвера
- CUBRID — SELECT, проекция, ORDER BY, LIMIT
Код и руководство с собой
Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.
Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.
Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.


