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

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

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

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

Глава 88 · После подключения, параметров и транзакций CUBRID

CUBRID: версии, кодировка и проверка соединения для рабочего каталога

Рабочий каталог с паспортом компонентов, точный UTF-8, разрешённый выбор базы и различение ping, ошибки SQL и пустой выборки.

Проверять конкретный маршрут данных, а не одну общую лампочку

Каталог перенесли на другой сервер: нужно понять, какие компоненты обслуживают запросы, сохранилось ли русское название, открыта ли нужная база и почему при успешном подключении иногда не работает SQL. В этой главе вы получите отчёт с двумя доступными товарами, точное чтение «Кабель O'Reilly», разрешённый выбор каталога и наглядное разделение трёх наблюдений: соединение отвечает, отдельный SQL ошибочен, подходящих строк нет.

Соединение можно представить как выбранный маршрут от PHP к конкретной базе. На маршруте есть PHP-модуль cubrid, клиентская библиотека CCI и сервер. У каждого своя версия. Имя базы обозначает адресата, кодировка — правило обмена текстом, а запрос — конкретное действие. Эта модель помогает разделить вопросы, но маршрут не обещает ни правильного SQL, ни прав на все таблицы, ни вечной доступности сервера.

Как получить понятный отчёт вместо одного «подключено»
  1. Модуль cubrid → CCI → открытое соединение к CUBRID: три отдельных номера версии
  2. Разрешённая база phpmanual168 и кодировка utf-8: сведения проверяем явно
  3. Конкретная операция: ограниченный SELECT каталога или INSERT известного текста → commit → SELECT
  4. Отчёт: Клипса и Кабель; точные байты названия; успешные строки отдельно от ошибки и пустого списка

Сначала одно сведение

// $db получен успешным cubrid_connect; его создание разобрано в начальной главе.
$charset = cubrid_get_charset($db);
if ($charset === false) {
    throw new RuntimeException('Не удалось узнать кодировку');
}
echo $charset; // utf-8 в примерах этой главы.

$db хранит ресурс соединения, круглыми скобками он передаётся функции, а возвращённая строка сохраняется в $charset. Строгое сравнение === false отделяет отказ. Это чтение информации, а не изменение настройки: функция не получает вторым аргументом желаемую кодировку и не переписывает строки. Основы вызовов объясняются в функциях, обычные строки — в строках. Следующий шаг — связать такое сведение с реальным действием и результатом.

ЗадачаЧто покажемПрактика
Перенос каталогаРаздельные версии + только доступные товары до заданной ценыОтчёт с конкретными строками
Название не должно испортитьсяКириллица, апостроф, точные байты и безопасный HTMLЗапись и чтение текста
Служебный выбор базыСписок → allowlist → новое соединение → DATABASE()Разрешённый каталог
«Подключено», но каталог не работаетping, ошибка поля, исправленный SELECT и пустой результатРазделение исходов

Перед этой главой нужны подключение и создание собственной таблицы, подготовленные параметры и commit/rollback. Полные файлы используют открытый вспомогательный lab.php для подготовки и очистки одной собственной таблицы. Все восемь новых функций вызываются в программах явно. Каждая программа самостоятельна; результаты HTML/JSON показывают реальные значения, а не только сообщение «успех».

Профиль воспроизведения закреплён: PHP 7.4.33 CLI, native cubrid 11.2.0.0002, CCI 11.2.0 и CUBRID 11.3.5. Это отдельное историческое окружение для данного API, не рекомендация менять PHP работающего сайта. Native cubrid и PDO_CUBRID не взаимозаменяются скрыто. README описывает подготовку самостоятельного изолированного стенда; пароли, приватные пути и подробные серверные ошибки в публичные результаты не попадают.

Отчёт для переноса каталога: какие компоненты работают и какие товары прочитаны

После переноса магазина администратор спрашивает: «Какие версии реально обслуживают каталог и работает ли нужная выборка?» Отчёт разделит три компонента и покажет два доступных товара не дороже 1500 копеек. Лента с нулевым остатком не попадёт на экран. Номера версий объясняют окружение, а полученные строки подтверждают конкретную операцию.

Путь конкретных значений
  1. PHP вызывает модуль cubrid 11.2.0.0002 → клиентская библиотека CCI 11.2.0
  2. Соединение ведёт к серверу 11.3.5.1274; сведения берутся из разных API
  3. SQL: parts, qty>0, цена≤1500, ORDER BY price_cents,id, LIMIT 2
  4. Экран: Клипса / 350 коп. / 12 шт. → Кабель / 1250 коп. / 4 шт.

Минимальная запись и её смысл

echo cubrid_version(); // Версия PHP-модуля: 11.2.0.0002 в этом профиле.
echo cubrid_get_client_info(); // Версия CCI: 11.2.0.
// $db — уже открытое соединение, не строка с именем базы.
$server = cubrid_get_server_info($db);
if ($server === false) { throw new RuntimeException('Версия сервера недоступна'); }
echo $server; // 11.3.5.1274 в этом профиле.

Пустые круглые скобки означают вызов без аргументов: модуль и его клиентская библиотека доступны в процессе PHP. Сервер выбирается через аргумент $db, поэтому его версия требует нужного соединения. Присваивание сохраняет возвращённую строку. Сравнение === false отличает отказ от строки. В полной программе c168Read подготавливает значения category и верхней цены отдельно от SQL; порядок и ограничение задаёт база, PHP только подписывает две строки.

Результат самостоятельной программы

НаблюдениеРезультат
PHP-модуль cubrid11.2.0.0002
Клиентская библиотека CCI11.2.0
Сервер11.3.5.1274
Кодировка соединенияutf-8
Товар 1Клипса / 350 коп. / 12 шт.
Товар 2Кабель / 1250 коп. / 4 шт.
Товар без остатка скрытда
Полная программа, файлы и архив для запуска
Отчёт для переноса каталога: какие компоненты работают и какие товары прочитаныСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/lab.php';
$db=null;$owned=$removed=$rows=$checks=$observations=[];
try {
    $config=c168Config();$db=c168Connect();$runtime=c168Runtime($db);

    $name=c168CreateTable($db,$owned,'compatibility',[
        ['id'=>10,'sku'=>'CAB-168','title'=>'Кабель','category'=>'parts','price_cents'=>1250,'qty'=>4,'note'=>null],
        ['id'=>20,'sku'=>'TAPE-168','title'=>'Лента','category'=>'parts','price_cents'=>240,'qty'=>0,'note'=>null],
        ['id'=>30,'sku'=>'CLIP-168','title'=>'Клипса','category'=>'parts','price_cents'=>350,'qty'=>12,'note'=>'В наличии']
    ]);
    $module=cubrid_version();
    $client=c168Capture(static function(){return cubrid_get_client_info();});
    $server=c168Capture(static function()use($db){return cubrid_get_server_info($db);});
    $charset=c168Capture(static function()use($db){return cubrid_get_charset($db);});
    foreach([$client,$server,$charset] as $call) {
        if (!is_string($call['value']) || $call['value']==='' || $call['warning']) {c168Failure('Сведения о компонентах недоступны',$call);}
    }
    $items=c168Read($db,'SELECT sku,title,price_cents,qty FROM '.c168Qualified($name)
        .' WHERE category=? AND qty>0 AND price_cents<=? ORDER BY price_cents,id LIMIT 2',['parts',1500]);
    c168Commit($db);
    $captions=[];
    foreach($items as $item) {$captions[]=$item['title'].' / '.(int)$item['price_cents'].' коп. / '.(int)$item['qty'].' шт.';}
    $rows=[['PHP-модуль cubrid',$module],['Клиентская библиотека CCI',$client['value']],
        ['Сервер',$server['value']],['Кодировка соединения',$charset['value']],
        ['Товар 1',$captions[0]??''],['Товар 2',$captions[1]??''],['Товар без остатка скрыт',!in_array('TAPE-168',array_column($items,'sku'),true)]];
    $checks=['module_reported'=>is_string($module)&&$module!=='','module_profile'=>$module==='11.2.0.0002',
        'client_profile'=>$client['value']==='11.2.0','server_profile'=>$server['value']==='11.3.5.1274',
        'charset_utf8'=>$charset['value']==='utf-8','two_bounded_rows'=>count($items)===2,
        'price_order'=>array_column($items,'sku')===['CLIP-168','CAB-168'],
        'first_caption'=>($captions[0]??null)==='Клипса / 350 коп. / 12 шт.',
        'second_caption'=>($captions[1]??null)==='Кабель / 1250 коп. / 4 шт.',
        'zero_stock_excluded'=>!in_array('TAPE-168',array_column($items,'sku'),true)];
    $observations=['components'=>['php_module'=>$module,'client'=>$client['value'],'server'=>$server['value'],'charset'=>$charset['value']],
        'catalog_rows'=>$items,'projection'=>['sku','title','price_cents','qty'],
        'filter'=>['category'=>'parts','qty_greater_than'=>0,'maximum_price_cents'=>1500],'limit'=>2];

} finally {
    if (function_exists('c168LockChildStopped') && !c168LockChildStopped()) {
        throw new RuntimeException('Дочерний процесс ещё работает; очистка таблицы запрещена до его остановки.');
    }
    if (is_resource($db)) {try {$removed=c168Cleanup($db,$owned);} finally {c168Close($db);}}
}

c168Report('cub168-compatibility-report','Отчёт для переноса каталога: какие компоненты работают и какие товары прочитаны',$rows,$checks,$observations,$runtime,$owned,$removed);
Ожидаемый результат
PHP-модуль cubrid — 11.2.0.0002
Клиентская библиотека CCI — 11.2.0
Сервер — 11.3.5.1274
Кодировка соединения — utf-8
Товар 1 — Клипса / 350 коп. / 12 шт.
Товар 2 — Кабель / 1250 коп. / 4 шт.
Товар без остатка скрыт — да

Распакуйте все файлы и выполните example.php по README.txt. lab.php проверяет отдельную базу и namespace, создаёт одну собственную таблицу и удаляет её в finally. result.html показывает полезный результат, result.json — строки и наблюдения, metrics.json — проверки и очистку. Условия реального запуска отличаются от простой проверки синтаксиса.

Открыть фактический результат · Открыть данные JSON.

Ошибки и границы

Версии не обязаны совпадать текстом: это разные компоненты. Не превращайте равенство номеров в произвольный критерий совместимости. Поддержку конкретной функции сверяют с документацией и проверяют своей операцией. Одно успешное чтение не подтверждает все виды записи, LOB, права и обновления. Полный phpinfo может содержать лишние сведения; отчёт выбирает только нужные поля. Наблюдаемые версии относятся к отдельному историческому профилю PHP 7.4.33, а не к PHP сайта.

Вопрос о проверке требований установки смешивал сведения о локальном клиенте и версии сервера без подключения. Исходное обсуждение. Наш отчёт разделяет модуль, CCI и сервер и добавляет реальный запрос каталога. Чужие shell-команды и MySQL API не переносятся.

Измените требование

Цена для экранного списка снижена до 500 копеек. Нужно ли получить все товары и удалить дорогие в PHP?

Разбор решения

Нет. Передайте 500 вместо 1500 в подготовленный WHERE и оставьте LIMIT. В этом наборе получится только Клипса. Отчёт о компонентах не меняет SQL-отбор и не оправдывает загрузку полной таблицы.

Проверить сохранение названия с кириллицей и апострофом

Поставщик прислал товар «Кабель O'Reilly». Нужно сохранить русские буквы и апостроф без исправлений наугад. Программа запишет название через параметры, прочитает его после commit и сравнит исходные и полученные байты. На экране будет исходная строка, размер 21 байт и примечание с буквальными <склад> и &, а не HTML-разметкой.

Путь конкретных значений
  1. UTF-8 строка «Кабель O'Reilly»: 21 байт передаётся значением параметра
  2. Соединение сообщает utf-8 через get_charset и client_encoding; оба лишь читают настройку
  3. INSERT → commit → SELECT title,note,qty WHERE id=10 LIMIT 1
  4. Точное сравнение и SHA-256: те же байты; HTML-отчёт отдельно экранирует текст

Минимальная запись и её смысл

$charset = cubrid_get_charset($db);
if ($charset === false) { throw new RuntimeException('Кодировка недоступна'); }
echo $charset; // utf-8 в подготовленной базе.
$sameInformation = cubrid_client_encoding($db);
// Этот вызов ничего не перекодирует и не меняет уже сохранённый текст.

Charset — правило соответствия байтов символам. Здесь строка UTF-8 в исходном файле, соединение и база согласованы. Аргумент $db указывает конкретное соединение. Название функции client_encoding не означает «перекодировать»: возвращается название текущей кодировки. Апостроф относится к данным и передаётся через bind, поэтому не закрывает SQL-кавычку. strlen считает байты; сравнение SHA-256 дополняет прямое === и удобно для больших контрольных образцов. HTML-экранирование решает другую задачу: показать угловые скобки как текст.

Результат самостоятельной программы

НаблюдениеРезультат
Исходное названиеКабель O'Reilly
Полученное названиеКабель O'Reilly
Байт UTF-8 в названии21
get_charsetutf-8
client_encodingutf-8
Байты совпалида
ПримечаниеПроверено <склад> & упаковка
Getters не изменили кодировкуда
Полная программа, файлы и архив для запуска
Проверить сохранение названия с кириллицей и апострофомСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/lab.php';
$db=null;$owned=$removed=$rows=$checks=$observations=[];
try {
    $config=c168Config();$db=c168Connect();$runtime=c168Runtime($db);

    $name=c168CreateTable($db,$owned,'charset');$table=c168Qualified($name);
    $title="Кабель O'Reilly";$note='Проверено <склад> & упаковка';
    $before=c168Capture(static function()use($db){return cubrid_get_charset($db);});
    $compat=c168Capture(static function()use($db){return cubrid_client_encoding($db);});
    if (!is_string($before['value']) || !is_string($compat['value']) || $before['warning'] || $compat['warning']) {
        c168Failure('Кодировка соединения не прочитана',$compat);
    }
    $written=c168Command($db,'INSERT INTO '.$table.' (id,sku,title,category,price_cents,qty,note) VALUES (?,?,?,?,?,?,?)',
        [10,'TEXT-168',$title,'parts',1250,4,$note]);
    c168Commit($db);
    $items=c168Read($db,'SELECT title,note,qty FROM '.$table.' WHERE id=? LIMIT 1',[10]);
    $after=c168Capture(static function()use($db){return cubrid_get_charset($db);});
    c168Commit($db);
    if (count($items)!==1) {throw new RuntimeException('Сохранённый товар не прочитан.');}
    $stored=$items[0]['title'];$sameBytes=hash_equals(hash('sha256',$title),hash('sha256',$stored));
    $rows=[['Исходное название',$title],['Полученное название',$stored],['Байт UTF-8 в названии',strlen($stored)],
        ['get_charset',$before['value']],['client_encoding',$compat['value']],['Байты совпали',$sameBytes],
        ['Примечание',$items[0]['note']],['Getters не изменили кодировку',$before['value']===$after['value']]];
    $checks=['inserted_one'=>$written===1,'read_one'=>count($items)===1,'title_exact'=>$stored===$title,
        'byte_identity'=>$sameBytes,'title_bytes'=>strlen($stored)===21,'valid_utf8'=>preg_match('//u',$stored)===1,
        'charset_utf8'=>$before['value']==='utf-8','compatible_getter'=>$compat['value']===$before['value'],
        'getter_preserves_charset'=>$after['value']===$before['value'],'after_no_warning'=>!$after['warning'],
        'note_exact'=>$items[0]['note']===$note,'quantity_preserved'=>$items[0]['qty']==='4'];
    $observations=['input'=>['title'=>$title,'note'=>$note],'stored_row'=>$items[0],
        'sha256_input'=>hash('sha256',$title),'sha256_readback'=>hash('sha256',$stored),
        'input_bytes'=>strlen($title),'readback_bytes'=>strlen($stored),
        'charset_before'=>$before['value'],'charset_after'=>$after['value'],'client_encoding'=>$compat['value']];

} finally {
    if (function_exists('c168LockChildStopped') && !c168LockChildStopped()) {
        throw new RuntimeException('Дочерний процесс ещё работает; очистка таблицы запрещена до его остановки.');
    }
    if (is_resource($db)) {try {$removed=c168Cleanup($db,$owned);} finally {c168Close($db);}}
}

c168Report('cub168-charset-roundtrip','Проверить сохранение названия с кириллицей и апострофом',$rows,$checks,$observations,$runtime,$owned,$removed);
Ожидаемый результат
Исходное название — Кабель O'Reilly
Полученное название — Кабель O'Reilly
Байт UTF-8 в названии — 21
get_charset — utf-8
client_encoding — utf-8
Байты совпали — да
Примечание — Проверено <склад> & упаковка
Getters не изменили кодировку — да

Распакуйте все файлы и выполните example.php по README.txt. lab.php проверяет отдельную базу и namespace, создаёт одну собственную таблицу и удаляет её в finally. result.html показывает полезный результат, result.json — строки и наблюдения, metrics.json — проверки и очистку. Условия реального запуска отличаются от простой проверки синтаксиса.

Открыть фактический результат · Открыть данные JSON.

Ошибки и границы

Название utf-8 само по себе не доказывает, что прежние записи корректны: в базе уже могли сохраниться вопросительные знаки или двойное кодирование. Getters не восстанавливают утраченные символы. Этот опыт доказывает точное прохождение выбранной новой строки, а не качество всей исторической базы. Не применяйте utf8_encode или SET NAMES из ответа про другую СУБД без понимания исходных байтов и API. Пароль не участвует в отчёте или хешировании.

Автор пытался понять, корректно ли хранятся старые строки, если после изменения кодировки соединения часть текста выглядит нормально. Исходное обсуждение. Здесь новый известный образец записывается параметром и сравнивается побайтно после чтения. Это проверка выбранного маршрута, а не обещание исправления исторических данных.

Измените требование

Текст выглядит правильно, но из внешнего файла приходит другая последовательность байтов. Достаточно ли увидеть utf-8 в getter?

Разбор решения

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

Выбрать разрешённую базу из списка и подтвердить, какой каталог открыт

В служебном интерфейсе можно выбрать каталог, но нельзя превращать любой присланный адрес или имя базы в подключение. Пример получает список имён, оставляет только собственную разрешённую базу и показывает её понятную подпись. Затем отдельное подключение подтверждает своё DATABASE() и читает «Набор крепежа — 6 шт.». Внешний выбор customer-production отвергается до открытия соединения.

Путь конкретных значений
  1. list_dbs возвращает массив имён; db_name(list,index) достаёт одно имя по позиции от 0
  2. Пересечение с allowlist: phpmanual168 → подпись «Учебный каталог»
  3. Ветвление: разрешённый выбор открываем; customer-production отклоняем без соединения
  4. Новый ресурс подтверждает DATABASE()=phpmanual168 и выбирает только доступные kits

Минимальная запись и её смысл

$names = cubrid_list_dbs($db);
if ($names === false) { throw new RuntimeException('Список баз недоступен'); }
if (count($names) > 0) {
    $firstName = cubrid_db_name($names, 0);
    echo $firstName; // phpmanual168 в этом отдельном стенде.
}

list_dbs возвращает обычный PHP-массив, а не request с SQL-строками. Первый аргумент db_name — именно этот массив; второй — его позиция от нуля. Функция не переключает соединение. Allowlist — явно заданная карта разрешённых имён и подписей; наличие имени в списке сервера не заменяет разрешение приложения. В самостоятельной программе второй ресурс действительно открывается после проверки выбора, а SQL DATABASE() подтверждает его назначение. Конфигурация урока разрешает только собственную учебную базу.

Результат самостоятельной программы

НаблюдениеРезультат
Разрешённых вариантов1
Подпись выбораУчебный каталог
База подтверждена SQLphpmanual168
Каталог выбранной базыНабор крепежа — 6 шт.
Чужой выбор отклонён до подключенияда
Индекс за границей списка отклонёнда
Полная программа, файлы и архив для запуска
Выбрать разрешённую базу из списка и подтвердить, какой каталог открытСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/lab.php';
$db=null;$owned=$removed=$rows=$checks=$observations=[];
try {
    $config=c168Config();$db=c168Connect();$runtime=c168Runtime($db);

    $name=c168CreateTable($db,$owned,'selection',[
        ['id'=>1,'sku'=>'KIT-168','title'=>'Набор крепежа','category'=>'kits','price_cents'=>890,'qty'=>6,'note'=>null],
        ['id'=>2,'sku'=>'BOX-168','title'=>'Коробка','category'=>'packing','price_cents'=>190,'qty'=>8,'note'=>'']
    ]);
    $listed=c168Capture(static function()use($db){return cubrid_list_dbs($db);});
    if (!is_array($listed['value']) || $listed['warning']) {c168Failure('Список баз недоступен',$listed);}
    $databases=$listed['value'];$allowed=[$config['database']=>'Учебный каталог'];$visible=[];
    foreach(array_keys($databases) as $index) {
        $candidate=cubrid_db_name($databases,(int)$index);
        if ($candidate===false) {throw new RuntimeException('Имя из списка не прочитано.');}
        if (array_key_exists($candidate,$allowed)) {$visible[$candidate]=$allowed[$candidate];}
    }
    $chosen=$config['database'];$foreignChoice='customer-production';
    $foreignDenied=!array_key_exists($foreignChoice,$visible);
    if (!array_key_exists($chosen,$visible)) {throw new RuntimeException('Учебная база не входит в разрешённый список.');}
    $outside=cubrid_db_name($databases,count($databases));
    c168Commit($db);$selectedDb=null;
    try {
        // chosen прошёл allowlist; c168Connect открывает именно эту учебную конфигурацию.
        $selectedDb=c168Connect(true);
        $identity=c168Read($selectedDb,'SELECT DATABASE() AS database_name');
        $catalog=c168Read($selectedDb,'SELECT sku,title,qty FROM '.c168Qualified($name)
            .' WHERE category=? AND qty>0 ORDER BY id LIMIT 2',['kits']);
        c168Commit($selectedDb);
    } finally {c168Close($selectedDb);}
    $actual=$identity[0]['database_name']??null;
    $caption=isset($catalog[0])?$catalog[0]['title'].' — '.(int)$catalog[0]['qty'].' шт.':'';
    $rows=[['Разрешённых вариантов',count($visible)],['Подпись выбора',$visible[$chosen]],
        ['База подтверждена SQL',$actual],['Каталог выбранной базы',$caption],
        ['Чужой выбор отклонён до подключения',$foreignDenied],['Индекс за границей списка отклонён',$outside===false]];
    $checks=['list_is_array'=>is_array($databases),'own_database_listed'=>in_array($config['database'],$databases,true),
        'only_allowed_visible'=>array_keys($visible)===[$config['database']],
        'foreign_denied_before_connect'=>$foreignDenied,'out_of_range_false'=>$outside===false,
        'identity_one_row'=>count($identity)===1,'selected_database_confirmed'=>$actual===$chosen,
        'catalog_one_row'=>count($catalog)===1,'catalog_sku'=>($catalog[0]['sku']??null)==='KIT-168',
        'catalog_caption'=>$caption==='Набор крепежа — 6 шт.','second_connection_closed'=>$selectedDb===null];
    $observations=['database_names'=>$databases,'allowed_names'=>array_keys($allowed),'visible_choices'=>$visible,
        'chosen'=>$chosen,'actual_database'=>$actual,'catalog_rows'=>$catalog,
        'invalid_index'=>count($databases),'invalid_index_return'=>$outside,'foreign_attempt_connected'=>false];

} finally {
    if (function_exists('c168LockChildStopped') && !c168LockChildStopped()) {
        throw new RuntimeException('Дочерний процесс ещё работает; очистка таблицы запрещена до его остановки.');
    }
    if (is_resource($db)) {try {$removed=c168Cleanup($db,$owned);} finally {c168Close($db);}}
}

c168Report('cub168-database-selection','Выбрать разрешённую базу из списка и подтвердить, какой каталог открыт',$rows,$checks,$observations,$runtime,$owned,$removed);
Ожидаемый результат
Разрешённых вариантов — 1
Подпись выбора — Учебный каталог
База подтверждена SQL — phpmanual168
Каталог выбранной базы — Набор крепежа — 6 шт.
Чужой выбор отклонён до подключения — да
Индекс за границей списка отклонён — да

Распакуйте все файлы и выполните example.php по README.txt. lab.php проверяет отдельную базу и namespace, создаёт одну собственную таблицу и удаляет её в finally. result.html показывает полезный результат, result.json — строки и наблюдения, metrics.json — проверки и очистку. Условия реального запуска отличаются от простой проверки синтаксиса.

Открыть фактический результат · Открыть данные JSON.

Ошибки и границы

Список существующих баз может быть служебной информацией: не показывайте его целиком анонимному посетителю. Порядок массива не является постоянным идентификатором клиента; сохранённую позицию нельзя переносить на новый список без проверки. cubrid_db_name при неверном индексе может вернуть false без новой SQL-ошибки: это локальное чтение массива. Результат не утверждает права на все базы. Реальный многоклиентский сервис дополнительно проверяет владельца и использует отдельные разрешённые реквизиты, а не один административный пароль для произвольного выбора.

Измените требование

Если список завтра изменил порядок, можно ли хранить в настройках только выбранное число 0?

Разбор решения

Нет. Храните устойчивый разрешённый ключ конфигурации и при открытии сопоставляйте его с нужным именем. Индекс 0 описывает конкретный массив этого вызова. При отсутствии разрешённой базы покажите отказ выбора, а не подключайтесь к первому попавшемуся имени.

Сервер отвечает, а запрос неверен: разделить три исхода задачи

Кнопка «Проверить соединение» показывает успех, а каталог не открывается. Нужно различить недоступное соединение, ошибочный SQL и успешную выборку без строк. Здесь ping ответит true, запрос несуществующего поля будет отклонён, исправленный SELECT покажет «Сканер — 2 шт.», а поиск другой категории законно вернёт пустой список. Сервер работает всё время.

Путь конкретных значений
  1. ping(db)=true: минимальная проверка отвечает, но будущий SELECT ещё не выполнен
  2. SELECT missing_column_168 → false; немедленно сохраняем code/facility/warning
  3. rollback завершает границу; ping снова true; правильный SELECT возвращает Сканер / 2
  4. SELECT другой категории → [] без ошибки: выводим «Ничего не найдено», а не «Сервер упал»

Минимальная запись и её смысл

$alive = cubrid_ping($db);
if ($alive !== true) {
    throw new RuntimeException('Соединение не отвечает');
}
// true относится к этому вызову. Следующий SQL проверяется самостоятельно.
$request = cubrid_execute($db, 'SELECT 1 AS connection_sample');
if ($request === false) { throw new RuntimeException('SQL не выполнен'); }
cubrid_close_request($request);

Bool true/false относится к проверке соединения, не к существованию столбца или нужного товара. Полная программа намеренно ошибается только в заранее известном названии поля собственной таблицы. c168Capture сохраняет диагностические значения сразу, до rollback и второго ping. Сырой текст ошибки не публикуется: он может содержать имена и пути. После исправления SQL запрос проверяется заново; пустой массив строк означает другое состояние интерфейса. Мы не добавляем автоматический повтор записи после любого false.

Результат самостоятельной программы

НаблюдениеРезультат
Соединение до запроса отвечаетда
Неверный SELECT отклонёнда
Причина задачиВыбрано несуществующее поле
Соединение после отказа отвечаетда
Исправленный SELECTСканер — 2 шт.
Строк в пустой выборке0
Пустая выборка является SQL-ошибкойнет
Полная программа, файлы и архив для запуска
Сервер отвечает, а запрос неверен: разделить три исхода задачиСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/lab.php';
$db=null;$owned=$removed=$rows=$checks=$observations=[];
try {
    $config=c168Config();$db=c168Connect();$runtime=c168Runtime($db);

    $name=c168CreateTable($db,$owned,'probe',[
        ['id'=>1,'sku'=>'SCAN-168','title'=>'Сканер','category'=>'equipment','price_cents'=>12900,'qty'=>2,'note'=>null]
    ]);$table=c168Qualified($name);
    $before=c168Capture(static function()use($db){return cubrid_ping($db);});
    if ($before['value']!==true || $before['warning']) {c168Failure('Соединение не отвечает',$before);}
    $bad=c168Capture(static function()use($db,$table){return cubrid_execute($db,'SELECT missing_column_168 FROM '.$table.' WHERE id=1 LIMIT 1');});
    if (is_resource($bad['value'])) {$unexpected=$bad['value'];c168Release($unexpected);throw new RuntimeException('Ожидаемый отказ неизвестного поля не произошёл.');}
    // Диагностика уже сохранена; следующая операция вправе её заменить.
    $failure=['code'=>$bad['code'],'facility'=>$bad['facility'],'warning'=>$bad['warning'],'message_present'=>$bad['message_present']];
    c168Rollback($db);
    $after=c168Capture(static function()use($db){return cubrid_ping($db);});
    if ($after['value']!==true || $after['warning']) {c168Failure('Соединение после отмены не отвечает',$after);}
    $items=c168Read($db,'SELECT title,qty FROM '.$table.' WHERE id=? LIMIT 1',[1]);
    $empty=c168Read($db,'SELECT title,qty FROM '.$table.' WHERE category=? ORDER BY id LIMIT 2',['not-listed']);
    c168Commit($db);
    $caption=isset($items[0])?$items[0]['title'].' — '.(int)$items[0]['qty'].' шт.':'';
    $rows=[['Соединение до запроса отвечает',$before['value']],['Неверный SELECT отклонён',$bad['value']===false],
        ['Причина задачи','Выбрано несуществующее поле'],['Соединение после отказа отвечает',$after['value']],
        ['Исправленный SELECT',$caption],['Строк в пустой выборке',count($empty)],['Пустая выборка является SQL-ошибкой',false]];
    $checks=['initial_ping_true'=>$before['value']===true,'bad_query_false'=>$bad['value']===false,
        'error_code_captured'=>$failure['code']===-494,'error_facility_captured'=>$failure['facility']===1,
        'error_warning_captured'=>$failure['warning'],'error_message_presence'=>$failure['message_present'],
        'ping_after_failure_true'=>$after['value']===true,'correct_query_one_row'=>count($items)===1,
        'correct_caption'=>$caption==='Сканер — 2 шт.','empty_query_succeeded'=>$empty===[],
        'stock_unchanged'=>($items[0]['qty']??null)==='2'];
    $observations=['ping_before'=>$before['value'],'failed_query_return'=>$bad['value'],'failed_query'=>$failure,
        'ping_after'=>$after['value'],'successful_rows'=>$items,'empty_rows'=>$empty,
        'server_was_stopped'=>false,'automatic_retries'=>0];

} finally {
    if (function_exists('c168LockChildStopped') && !c168LockChildStopped()) {
        throw new RuntimeException('Дочерний процесс ещё работает; очистка таблицы запрещена до его остановки.');
    }
    if (is_resource($db)) {try {$removed=c168Cleanup($db,$owned);} finally {c168Close($db);}}
}

c168Report('cub168-connection-probe','Сервер отвечает, а запрос неверен: разделить три исхода задачи',$rows,$checks,$observations,$runtime,$owned,$removed);
Ожидаемый результат
Соединение до запроса отвечает — да
Неверный SELECT отклонён — да
Причина задачи — Выбрано несуществующее поле
Соединение после отказа отвечает — да
Исправленный SELECT — Сканер — 2 шт.
Строк в пустой выборке — 0
Пустая выборка является SQL-ошибкой — нет

Распакуйте все файлы и выполните example.php по README.txt. lab.php проверяет отдельную базу и namespace, создаёт одну собственную таблицу и удаляет её в finally. result.html показывает полезный результат, result.json — строки и наблюдения, metrics.json — проверки и очистку. Условия реального запуска отличаются от простой проверки синтаксиса.

Открыть фактический результат · Открыть данные JSON.

Ошибки и границы

Между успешным ping и запросом сеть может перестать работать. Поэтому ping перед каждой операцией не устраняет обработку отказа самой операции и добавляет обращение к базе. В закреплённом исходнике эта функция выполняет служебный SELECT; это не ICMP-ping и не проверка HTTP. Заголовок исторической страницы упоминает reconnect, однако пример не обещает восстановление транзакции, сохранение сеанса или безопасный повтор записи. После неопределённого исхода изменения нужна отдельная политика идемпотентности и проверки результата.

Вопрос предлагает проверять соединение перед каждым запросом, чтобы гарантировать доступность сервера. Исходное обсуждение. Самостоятельный пример показывает успешный ping и неуспешный SQL, затем успешное чтение. CUBRID-правила взяты из официального исходника, не из MySQL-ответов.

Измените требование

Запрос вернул ноль товаров. Нужно ли сразу переподключаться и повторять запрос до появления строки?

Разбор решения

Нет. Сначала отделите отказ execute/fetch от успешного результата с нулём строк. Для отсутствующей категории здесь нормальный ответ — пустой список. Повтор не исправляет условие WHERE и может маскировать ошибку интерфейса. Переподключение решает потерю соединения, а не отсутствие подходящих данных.

Восемь функций по вопросу, на который они отвечают

ФункцияНазначение
cubrid_versionУзнать версию загруженного PHP-модуля cubrid и не спутать её с сервером.
cubrid_get_client_infoОпределить версию клиентской библиотеки CCI, через которую PHP общается с CUBRID.
cubrid_get_server_infoПолучить версию сервера по конкретному открытому соединению.
cubrid_get_charsetУзнать кодировку конкретного соединения перед диагностикой текстового обмена.
cubrid_client_encodingПрочитать кодировку соединения через имя из совместимого с MySQL набора CUBRID.
cubrid_list_dbsПолучить список имён баз для служебного выбора и сопоставления с разрешённой конфигурацией.
cubrid_db_nameДостать одно имя по позиции из массива, возвращённого cubrid_list_dbs.
cubrid_pingПроверить ответ соединения, отдельно от результата конкретной бизнес-операции.

От диагностики соединения к ограниченному ожиданию

Сведения о версиях, кодировке и доступности помогают объяснить условия работы. Итоговую задачу подтверждают выбранные строки, точное сохранение текста и проверенная граница транзакции. Имя из списка не даёт доступа само по себе, а успешный ping не заменяет результат SQL. Эти различия позволяют показать читателю понятную причину отказа и не маскировать её переподключением.

Далее — срок выполнения запроса, ожидание блокировки и изоляция. Глава о чтении строк и байтов помогает оформить результат; описание полей объясняет выбранные имена и типы. Основной принцип остаётся прежним: база выбирает нужные строки и порядок, PHP отображает именно то, что требуется сейчас.

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

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

cubrid_versionУзнать версию загруженного PHP-модуля cubrid и не спутать её с сервером.

PECL CUBRID >= 8.3.0; отдельный исторический профиль PHP/CCI/сервера. · cubrid

cubrid_version(): string

Узнать версию загруженного PHP-модуля cubrid и не спутать её с сервером.

Базовая запись

cubrid_version(): string

PECL CUBRID >= 8.3.0. Это версия появления API, а не обещание совместимости любого бинарного расширения с любым PHP. Справочная запись | означает варианты возврата; квадратные скобки вокруг аргумента означают необязательный аргумент, а не PHP-массив. Эти записи описывают контракт и не являются декларациями для запуска в PHP 7.4. В выполняемых программах соединение передаётся явно.

ПараметрСмысл
Нет параметровВызов относится к загруженному модулю текущего процесса PHP. Соединение с базой не требуется.
РезультатЧто он означает
stringВерсия PHP-модуля, например 11.2.0.0002 в проверенном профиле. Документация не задаёт false как обычный результат этого вызова.

PHP-модуль — расширение, добавляющее функции cubrid_*. CCI — отдельная клиентская библиотека, а сервер — процесс, который хранит данные и выполняет SQL. Числа 11.2.0.0002, 11.2.0 и 11.3.5.1274 имеют разных владельцев и не обязаны совпадать. В закреплённом исходнике cubrid_version возвращает строковую константу сборки модуля; это не сетевой запрос к серверу.

Применение 1: точное название компонента в отчёте

if (!extension_loaded('cubrid')) {
    throw new RuntimeException('Расширение cubrid не загружено');
}
$moduleVersion = cubrid_version();
echo 'PHP-модуль: '.$moduleVersion; // PHP-модуль: 11.2.0.0002

В отчёте переноса каталога эта подпись стоит рядом с реальными товарами. Она помогает воспроизвести проблему в нужной сборке. Проверка extension_loaded важна до вызова: отсутствие расширения означает отсутствие функции, а не возврат false от существующей функции.

Применение 2: приложить версию к точному образцу текста

// $original и $readBack — исходное и прочитанное названия товара.
$textReceipt = [
    'module' => cubrid_version(),
    'same_bytes' => $original === $readBack,
    'read_bytes' => strlen($readBack),
];

Такой небольшой отчёт развивает проверку «Кабель O'Reilly»: известны версия и факт точного прохождения 21 байта. Сведения о сборке не подменяют сравнение данных. Здесь достаточно выбранных полей, без вывода всего phpinfo и переменных окружения.

В этом историческом модуле phpversion("cubrid") фактически возвращает false, тогда как cubrid_version содержит номер сборки. Это два разных механизма метаданных; не заменяйте неизвестную версию догадкой. Если требуется версия CCI, используйте cubrid_get_client_info; версия сервера получается через cubrid_get_server_info. Сам номер не гарантирует наличие нужной настройки сервера, прав или исправления всех ошибок.

cubrid_get_client_infoОпределить версию клиентской библиотеки CCI, через которую PHP общается с CUBRID.

PECL CUBRID >= 8.3.0; отдельный исторический профиль PHP/CCI/сервера. · cubrid

cubrid_get_client_info(): string|false

Определить версию клиентской библиотеки CCI, через которую PHP общается с CUBRID.

Базовая запись

cubrid_get_client_info(): string|false

PECL CUBRID >= 8.3.0. Это версия появления API, а не обещание совместимости любого бинарного расширения с любым PHP. Справочная запись | означает варианты возврата; квадратные скобки вокруг аргумента означают необязательный аргумент, а не PHP-массив. Эти записи описывают контракт и не являются декларациями для запуска в PHP 7.4. В выполняемых программах соединение передаётся явно.

ПараметрСмысл
Нет параметровВерсия клиентской библиотеки текущего PHP-процесса. Аргумент $db здесь не нужен.
РезультатЧто он означает
Непустая строкаЗапрошенное сведение о компоненте или соединении. Не нужно приводить номер версии к float.
falseСведения получить не удалось; сохраните диагностику и не подставляйте фиктивное значение.

Клиентская библиотека CCI передаёт команды от PHP серверу. Это не браузер посетителя и не версия PHP. В закреплённом драйвере функция читает major/minor/patch через CCI и формирует строку из трёх компонентов. Публичный контракт сохраняет false при отказе; обработка не должна считать любую строку доказательством исправности сервера.

Применение 1: различить CCI и сервер при переносе

$client = cubrid_get_client_info();
if ($client === false) { throw new RuntimeException('Версия CCI недоступна'); }
echo 'Клиент CCI: '.$client; // Клиент CCI: 11.2.0

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

Применение 2: локализовать отличие двух запусков импорта

$client = cubrid_get_client_info();
$charset = cubrid_get_charset($db);
if ($client === false || $charset === false) {
    throw new RuntimeException('Диагностические сведения неполны');
}
$receipt = ['client' => $client, 'charset' => $charset, 'bytes_equal' => $original === $readBack];

При разном результате импорта на двух машинах сначала сравните такие сведения и одинаковый контрольный текст. Тот же исходник приложения может работать с другой CCI. Запись версии объясняет условия опыта, но не даёт права менять кодировку уже сохранённых записей.

Открытие второго соединения внутри одного процесса не загружает для него другую CCI автоматически. Для отличия адресатов нужен cubrid_get_server_info, а для имени самой базы — подтверждение SQL DATABASE(), как в разрешённом выборе каталога. Ошибочные аргументы относятся к вызову PHP: не передавайте resource в функцию без параметров.

cubrid_get_server_infoПолучить версию сервера по конкретному открытому соединению.

PECL CUBRID >= 8.3.0; отдельный исторический профиль PHP/CCI/сервера. · cubrid

cubrid_get_server_info(resource $conn_identifier): string|false

Получить версию сервера по конкретному открытому соединению.

Базовая запись

cubrid_get_server_info(resource $conn_identifier): string|false

PECL CUBRID >= 8.3.0. Это версия появления API, а не обещание совместимости любого бинарного расширения с любым PHP. Справочная запись | означает варианты возврата; квадратные скобки вокруг аргумента означают необязательный аргумент, а не PHP-массив. Эти записи описывают контракт и не являются декларациями для запуска в PHP 7.4. В выполняемых программах соединение передаётся явно.

ПараметрСмысл
conn_identifierОбязательный открытый ресурс соединения CUBRID. Это не request, имя базы или hostname.
РезультатЧто он означает
Непустая строкаЗапрошенное сведение о компоненте или соединении. Не нужно приводить номер версии к float.
falseСведения получить не удалось; сохраните диагностику и не подставляйте фиктивное значение.

Версия сервера относится к выбранному соединению. Если в приложении несколько баз или адресатов, передайте нужный ресурс. Наличие установленной локальной CCI не говорит, какой сервер находится на другом конце. Строку версии сохраняют целиком: приведение 11.3.5.1274 к float потеряет значимые части.

Применение 1: сервер в отчёте после реального подключения

$server = cubrid_get_server_info($db);
if ($server === false) { throw new RuntimeException('Версия сервера недоступна'); }
echo 'Сервер: '.$server; // Сервер: 11.3.5.1274

Так устроена подпись в отчёте с двумя доступными товарами. Номер берётся из сервера, а не из phpinfo. После него выполняется ограниченный запрос каталога: именно запрос проверяет требуемый путь чтения.

Применение 2: паспорт выбранного адресата

// $selectedDb — соединение после выбора разрешённой конфигурации.
$targetVersion = cubrid_get_server_info($selectedDb);
if ($targetVersion === false) { throw new RuntimeException('Адресат не подтверждён'); }
// Имя базы подтверждается отдельно: SELECT DATABASE() AS database_name.
$target = ['server' => $targetVersion, 'database' => $actualDatabase];

В маршруте выбора каталога версия и имя отвечают на разные вопросы. Два разных каталога могут обслуживаться одним сервером с одинаковой версией. Имя базы и право приложения на неё нельзя вывести из номера сборки.

Сведения не являются универсальной проверкой живого соединения: в закреплённом C-коде результат вызова получения версии не проверяется так же, как выполняемый запрос. Используйте корректно созданный ресурс и проверяйте нужную SQL-операцию; cubrid_ping тоже не гарантирует успех следующего запроса. Не трактуйте ложный или пустой результат как «очень старую версию» и не продолжайте миграцию по догадке.

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

PECL CUBRID >= 8.3.0; отдельный исторический профиль PHP/CCI/сервера. · cubrid

cubrid_get_charset(resource $conn_identifier): string|false

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

Базовая запись

cubrid_get_charset(resource $conn_identifier): string|false

PECL CUBRID >= 8.3.0. Это версия появления API, а не обещание совместимости любого бинарного расширения с любым PHP. Справочная запись | означает варианты возврата; квадратные скобки вокруг аргумента означают необязательный аргумент, а не PHP-массив. Эти записи описывают контракт и не являются декларациями для запуска в PHP 7.4. В выполняемых программах соединение передаётся явно.

ПараметрСмысл
conn_identifierОбязательное открытое соединение, кодировку которого нужно прочитать.
РезультатЧто он означает
Непустая строкаЗапрошенное сведение о компоненте или соединении. Не нужно приводить номер версии к float.
falseСведения получить не удалось; сохраните диагностику и не подставляйте фиктивное значение.

Кодировка описывает представление символов байтами. Эта функция возвращает её имя, например utf-8 в учебном профиле. Она не принимает желаемую кодировку и ничего не исправляет в тексте. Сравнение с cubrid_client_encoding полезно при чтении старого кода: два имени сообщают одно и то же свойство соединения.

Применение 1: контроль текстового импорта

$charset = cubrid_get_charset($db);
if ($charset === false) { throw new RuntimeException('Кодировка недоступна'); }
if ($charset !== 'utf-8') {
    throw new RuntimeException('Этот импорт рассчитан на UTF-8');
}
// Название передаётся подготовленным параметром, затем читается обратно.

В самостоятельном импорте названия после этой проверки сохраняется «Кабель O'Reilly» и подтверждается точное совпадение байтов. Условие utf-8 здесь — явное требование конкретного формата обмена. Оно не объявляет другие кодировки неправильными для любых задач.

Применение 2: объяснить расхождение окружений

$charset = cubrid_get_charset($db);
$server = cubrid_get_server_info($db);
if ($charset === false || $server === false) {
    throw new RuntimeException('Отчёт неполон');
}
$diagnostic = ['server' => $server, 'connection_charset' => $charset];

Эта часть отчёта переноса помогает сопоставить запуск старого и нового окружения. Название базы, кодировка соединения, кодировка входного файла и кодировка HTML — разные характеристики. Указание charset в метатеге не исправит байты, которые уже были повреждены при записи.

Для прежних записей используйте известный контрольный образец и анализ исходных данных; не запускайте массовое преобразование на основании одного getter. Функция не измеряет длину строки: для полученных данных это разобрано в байтах UTF-8. SQL NULL и пустой текст тоже не являются кодировками. При false сохраняйте диагностику сразу, до следующего API-вызова.

cubrid_client_encodingПрочитать кодировку соединения через имя из совместимого с MySQL набора CUBRID.

PECL CUBRID >= 8.3.1; отдельный исторический профиль PHP/CCI/сервера. · cubrid

cubrid_client_encoding([resource $conn_identifier]): string|false

Прочитать кодировку соединения через имя из совместимого с MySQL набора CUBRID.

Базовая запись

cubrid_client_encoding([resource $conn_identifier]): string|false

PECL CUBRID >= 8.3.1. Это версия появления API, а не обещание совместимости любого бинарного расширения с любым PHP. Справочная запись | означает варианты возврата; квадратные скобки вокруг аргумента означают необязательный аргумент, а не PHP-массив. Эти записи описывают контракт и не являются декларациями для запуска в PHP 7.4. В выполняемых программах соединение передаётся явно.

ПараметрСмысл
conn_identifierНеобязательный ресурс. По PHP Manual при пропуске используется последнее соединение, открытое cubrid_connect. В явном коде передавайте нужный ресурс.
РезультатЧто он означает
Непустая строкаЗапрошенное сведение о компоненте или соединении. Не нужно приводить номер версии к float.
falseСведения получить не удалось; сохраните диагностику и не подставляйте фиктивное значение.

Функция находится в историческом разделе совместимости CUBRID с MySQL API. Она работает с ресурсом CUBRID, а не mysqli и не PDO. Слово encoding в имени не делает её преобразователем строк: единственный аргумент — соединение. В закреплённом драйвере она использует тот же внутренний getter кодировки, что cubrid_get_charset.

Применение 1: заменить неявное соединение явным

// В старом коде могло быть cubrid_client_encoding() без аргумента.
$encoding = cubrid_client_encoding($db);
if ($encoding === false) { throw new RuntimeException('Кодировка недоступна'); }
echo $encoding; // utf-8

В записи кириллического названия аргумент $db устраняет вопрос, к какому подключению относится результат. Два getter дают одинаковое utf-8, а неизменность исходной строки подтверждается отдельным чтением. Не смешивайте этот API с вызовом настройки кодировки из MySQL-ответа.

Применение 2: проверить выбранный каталог, а не последнее случайное соединение

// $selectedDb — новый ресурс выбранного разрешённого каталога.
$encoding = cubrid_client_encoding($selectedDb);
if ($encoding === false) { throw new RuntimeException('Кодировка адресата неизвестна'); }
$canReadUtf8Catalog = $encoding === 'utf-8';

В программе выбора базы существуют два ресурса: исходный и выбранный. Явный аргумент сохраняет смысл даже после открытия второго. Логический признак подходит для проверки требования UTF-8, но не доказывает права на таблицу или отсутствие повреждений во всех записях.

Пропущенный аргумент — удобство старого интерфейса, а не способ найти базу по имени. Закрытый ресурс не нужно передавать повторно; проверяйте результаты создания и завершения соединения. В новом коде допустимо выбрать более явное имя cubrid_get_charset, сохранив те же данные и проверки. Изменение имени getter не меняет серверную кодировку.

cubrid_list_dbsПолучить список имён баз для служебного выбора и сопоставления с разрешённой конфигурацией.

PECL CUBRID >= 8.3.0; отдельный исторический профиль PHP/CCI/сервера. · cubrid

cubrid_list_dbs([resource $conn_identifier]): array|false

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

Базовая запись

cubrid_list_dbs([resource $conn_identifier]): array|false

PECL CUBRID >= 8.3.0. Это версия появления API, а не обещание совместимости любого бинарного расширения с любым PHP. Справочная запись | означает варианты возврата; квадратные скобки вокруг аргумента означают необязательный аргумент, а не PHP-массив. Эти записи описывают контракт и не являются декларациями для запуска в PHP 7.4. В выполняемых программах соединение передаётся явно.

ПараметрСмысл
conn_identifierОткрытый ресурс соединения. PHP Manual показывает необязательность; полные программы передают его явно, не полагаясь на неявный последний ресурс.
РезультатЧто он означает
arrayЧисловой массив имён существующих баз. Это готовые строки PHP, не результат для cubrid_fetch_assoc.
falseСписок получить не удалось. Пустой массив и false — разные результаты.

В закреплённом драйвере список получается служебным SELECT LIST_DBS() через текущее соединение. Функция описывает наличие имён на стороне сервера, не перечень пользователей веб-приложения и не список доступных этому посетителю каталогов. Массив не открывает отдельные подключения и не выбирает базу автоматически. Само получение списка также может завершиться отказом SQL.

Применение 1: только разрешённые пункты служебного выбора

$names = cubrid_list_dbs($db);
if ($names === false) { throw new RuntimeException('Список баз недоступен'); }
$allowed = ['phpmanual168' => 'Учебный каталог'];
$choices = [];
foreach ($names as $name) {
    if (isset($allowed[$name])) { $choices[$name] = $allowed[$name]; }
}

В самостоятельном выборе каталога остаётся один понятный пункт. Имя customer-production не становится разрешённым лишь потому, что пришло из формы. При подключении используют соответствующую проверенную конфигурацию, а не строку непроверенного адреса.

Применение 2: проверка ожидаемой базы в отчёте развёртывания

$names = cubrid_list_dbs($db);
if ($names === false) { throw new RuntimeException('Список недоступен'); }
$expectedExists = in_array($expectedDatabase, $names, true);
// При false проверьте конфигурацию; не выбирайте автоматически names[0].

Так можно расширить отчёт переноса до проверки нужного каталога. При этом успех перечисления и наличие имени ещё не подтверждают SQL-права или работоспособность таблиц. Последующий ограниченный SELECT остаётся обязательной проверкой конкретной задачи.

Официальная сигнатура и парсер 11.2.0.0002 допускают пропуск соединения, но его arginfo помечает один обязательный аргумент. Практические примеры не зависят от этого расхождения: передают $db. Не показывайте полный список посторонних баз публично. Для отдельного элемента используется cubrid_db_name; для текущей базы открытого ресурса — SQL DATABASE(), а не первый элемент массива. Не сортируйте список на месте, если далее рассчитываете сохранить прежние позиции.

cubrid_db_nameДостать одно имя по позиции из массива, возвращённого cubrid_list_dbs.

PECL CUBRID >= 8.3.1; отдельный исторический профиль PHP/CCI/сервера. · cubrid

cubrid_db_name(array $result, int $index): string|false

Достать одно имя по позиции из массива, возвращённого cubrid_list_dbs.

Базовая запись

cubrid_db_name(array $result, int $index): string|false

PECL CUBRID >= 8.3.1. Это версия появления API, а не обещание совместимости любого бинарного расширения с любым PHP. Справочная запись | означает варианты возврата; квадратные скобки вокруг аргумента означают необязательный аргумент, а не PHP-массив. Эти записи описывают контракт и не являются декларациями для запуска в PHP 7.4. В выполняемых программах соединение передаётся явно.

ПараметрСмысл
resultИменно массив, полученный от cubrid_list_dbs. Здесь слово result не означает ресурс SELECT.
indexЦелая позиция от 0 до count(result)−1 в этом массиве. Не идентификатор базы на сервере.
РезультатЧто он означает
stringИмя базы в указанной позиции. Функция не открывает и не переключает соединение.
falseПозиции нет либо имя не удалось извлечь. Это не обязательно новая SQL-ошибка.

Функция выбирает элемент уже полученного массива в PHP. В исходнике она не отправляет SQL, не получает новый список и не сбрасывает диагностический код. Поэтому при false старая ошибка в cubrid_error может относиться к прежней операции. В подготовленном профиле индексы count($names) и −1 вернули false без предупреждения или нового кода; программа сначала проверяет диапазон и возвращаемое значение.

Применение 1: достать имя для разрешённой подписи

$names = cubrid_list_dbs($db);
if ($names === false) { throw new RuntimeException('Список недоступен'); }
for ($index = 0; $index < count($names); $index++) {
    $name = cubrid_db_name($names, $index);
    if ($name !== false && isset($allowed[$name])) { $choices[$name] = $allowed[$name]; }
}

В выборе каталога имя phpmanual168 получает подпись «Учебный каталог». Индекс используется только для чтения этого списка; решение о доступе принимает allowlist. Перед выполнением такого фрагмента $allowed и $choices объявляют как в полном примере.

Применение 2: безопасно объяснить неверный выбор позиции

// $names — успешно полученный массив. Пользователь прислал позицию $index.
$name = ($index >= 0 && $index < count($names))
    ? cubrid_db_name($names, $index)
    : false;
$caption = $name === false ? 'Выбранного пункта больше нет' : 'Пункт найден';

Это отдельная ситуация интерфейса: список изменился между показом формы и её обработкой. Она не означает потерю сервера — сравните с разделением ошибки SQL и отсутствия данных. В приложении лучше хранить устойчивый разрешённый ключ конфигурации и заново проверять его, а не доверять позиции из старого списка.

Не передавайте массив строк товаров, ассоциативную карту произвольного вида или resource: контракт относится к числовому списку имён. Индекс начинается с нуля, как в обычном PHP-массиве, но не обязан совпадать с id какой-либо записи. Получение имени не является подключением. Для нового ресурса используют cubrid_connect и проверенную конфигурацию; для подтверждения назначения ресурса полезен DATABASE().

cubrid_pingПроверить ответ соединения, отдельно от результата конкретной бизнес-операции.

PECL CUBRID >= 8.3.1; отдельный исторический профиль PHP/CCI/сервера. · cubrid

cubrid_ping([resource $conn_identifier]): bool

Проверить ответ соединения, отдельно от результата конкретной бизнес-операции.

Базовая запись

cubrid_ping([resource $conn_identifier]): bool

PECL CUBRID >= 8.3.1. Это версия появления API, а не обещание совместимости любого бинарного расширения с любым PHP. Справочная запись | означает варианты возврата; квадратные скобки вокруг аргумента означают необязательный аргумент, а не PHP-массив. Эти записи описывают контракт и не являются декларациями для запуска в PHP 7.4. В выполняемых программах соединение передаётся явно.

ПараметрСмысл
conn_identifierНеобязательный ресурс. При пропуске по PHP Manual берётся последнее соединение cubrid_connect; явно переданный $db устраняет неоднозначность.
РезультатЧто он означает
trueСоединение ответило на эту проверку. Следующая операция ещё не выполнена.
falseРаботоспособность соединения подтвердить не удалось. Сохраните текущую диагностику.

Это не команда операционной системы ping и не тест любого TCP-порта. В исходнике 11.2.0.0002 функция выполняет через CCI служебный SELECT 1 FROM db_root. Результат относится к этому пути проверки. Правильность вашей таблицы, имени столбца, прав и бизнес-условий проверяется самой нужной операцией.

Применение 1: различить ошибку SQL и потерю соединения

$alive = cubrid_ping($db);
if ($alive !== true) { throw new RuntimeException('Соединение не отвечает'); }
// Далее выполните нужный SELECT и отдельно проверьте его результат.
// true не означает, что колонка missing_column_168 существует.

В сценарии трёх исходов служебная проверка успешна, неверное поле даёт отказ, а исправленный запрос читает Сканер. Диагностика сохраняется сразу после отказа: последующий ping может сбросить прежний код. Пустая выборка — нормальный третий исход, а не повод объявлять соединение потерянным.

Применение 2: отдельный диагностический этап перед служебным отчётом

$connectionResponds = cubrid_ping($db);
if ($connectionResponds === true) {
    $serverVersion = cubrid_get_server_info($db);
    // Затем отдельный bounded SELECT получает строки для отчёта.
} else {
    // Сообщите отказ проверки; не выдавайте старый каталог за свежий.
}

Это уместно как явная часть отчёта администратора, где нужно показать несколько разных наблюдений. В обычном отображении карточки нет необходимости автоматически вставлять ping перед каждым execute: всё равно нужен контроль самого execute/fetch. Не заменяйте функцию бесконечным опросом без паузы и лимита.

Исторический заголовок PHP Manual говорит о ping или переподключении, но контракт true/false не обещает восстановить незавершённую транзакцию, состояние сеанса или уже созданный request. В закреплённом исходнике нет отдельной PHP-ветки reconnect внутри этой функции; нижележащие настройки нельзя выдавать за гарантию восстановления бизнес-действия. При неопределённом результате записи не повторяйте её вслепую: нужны явные границы транзакции и защита от повторного выполнения на уровне приложения. Срок ожидания операции рассматривается в тайм-аутах CUBRID.

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

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

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

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

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