客户希望使用php8.5.8进行开发,但达梦数据库之前没有php8.5版本的驱动,向开发提需求后得到了开发提供的该版本驱动,需要进行测试,确认确实能连接php8.5
| 内容 | 版本/类型 |
|---|---|
| 操作系统 | Kylin-Server-V10-SP3-2403 |
| CPU | x86_64bit |
| 达梦数据库 | 达梦9(达梦8也可用) |
| php | 8.5.8 |
因为麒麟的软件源里php最新只到8.0,所以从php官方下载源码编译安装
安装完成
[root@localhost ~]# php -v
PHP 8.5.8 (cli) (built: Aug 17 2026 10:58:25) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.5.8, Copyright (c) Zend Technologies
with Zend OPcache v8.5.8, Copyright (c), by Zend Technologies
确认php8.5的扩展目录在哪
# 确认php的扩展目录
[root@localhost php-8.5.8]# php -i | grep extension_dir
extension_dir => /usr/local/php858/lib/php/extensions/no-debug-non-zts-20250925 => /usr/local/php858/lib/php/extensions/no-debug-non-zts-20250925
sqlite3.extension_dir => no value => no value
复制达梦驱动到php的扩展目录,这里因为是php8.5.8版本,需要复制名字里带85(代表php8.5.x版本)的驱动
[root@localhost x86_kylin10_sp1_64]# cp libphp85_dm.so php85_pdo_dm.so /usr/local/php858/lib/php/extensions/no-debug-non-zts-20250925/ [root@localhost x86_kylin10_sp1_64]# ls -la /usr/local/php858/lib/php/extensions/no-debug-non-zts-20250925/ | grep dm -rw-r--r-- 1 root root 132512 8月 17 11:29 libphp85_dm.so -rw-r--r-- 1 root root 74016 8月 17 11:29 php85_pdo_dm.so
修改php.ini,让php能够加载达梦驱动
[root@localhost x86_kylin10_sp1_64]# vi /usr/local/php858/etc/php.ini
在末尾添加
[PHP_DM]
extension = libphp85_dm.so
extension = php85_pdo_dm.so
[dm]
dm.port = 5236
dm.allow_persistent = 1
dm.max_persistent = -1
dm.max_links = -1
dm.default_host = localhost
dm.default_db = SYSTEM
dm.default_user = SYSDBA
dm.default_pw = Dameng123
dm.connect_timeout = 10
dm.defaultlrl = 4096
dm.defaultbinmode = 1
dm.check_persistent = ON
设置环境变量
[root@localhost x86_kylin10_sp1_64]# export LD_LIBRARY_PATH=/data/dmdbms/bin:$LD_LIBRARY_PATH
检查php扩展是否安装成功
[root@localhost ~]# php -m | grep -i dm dm PDO_DM
扩展安装成功,测试一下连接是否成功
[root@localhost ~]# php -r "
> try {
> \$dbh = new PDO('dm:host=localhost;port=5236;dbname=SYSTEM', 'SYSDBA', 'Dameng123');
> echo '连接成功!' . PHP_EOL;
> } catch (PDOException \$e) {
> echo '连接失败:' . \$e->getMessage() . PHP_EOL;
> }
> "
连接成功!
连接成功,测试一下建表,建个和客户一样的表
# 先创建模式
[root@localhost ~]# php -r "\$dbh = new PDO('dm:host=localhost;port=5236;dbname=SYSTEM', 'SYSDBA', 'Dameng123'); \$dbh->exec('CREATE SCHEMA \"gw_etc\"'); echo '模式创建成功' . PHP_EOL;"
模式创建成功
# 然后建表
[root@localhost ~]# vi /tmp/create_table.php
写入如下内容
<?php
$dbh = new PDO('dm:host=localhost;port=5236;dbname=SYSTEM', 'SYSDBA', 'Dameng123');
$sql = <<<SQL
CREATE TABLE "gw_etc"."admininfo" (
"id" INT IDENTITY(3, 1) NOT NULL,
"admin_id" VARCHAR(64 CHAR) DEFAULT '' NOT NULL,
"admin_pass" VARCHAR(64 CHAR),
"admin_type" VARCHAR(11 CHAR) DEFAULT '' NOT NULL,
"admin_purview" TINYINT DEFAULT 0 NOT NULL,
"admin_name" VARCHAR(16 CHAR),
"admin_desc" VARCHAR(128 CHAR),
"change_password" TINYINT DEFAULT 1 NOT NULL,
"enable_flag" TINYINT DEFAULT 1 NOT NULL,
"expired_time" BIGINT DEFAULT 0,
"comment" VARCHAR(128 CHAR),
"domain_name" TEXT NOT NULL,
NOT CLUSTER PRIMARY KEY("id"),
CONSTRAINT "uni@gw_etc@admininfo@admin_id" UNIQUE("admin_id")
) STORAGE(ON "MAIN", CLUSTERBTR);
SQL;
$dbh->exec($sql);
echo "表 admininfo 创建成功\n";
[root@localhost ~]# php /tmp/create_table.php
表 admininfo 创建成功
# 验证表记录数
[root@localhost ~]# php -r "
> \$dbh = new PDO('dm:host=localhost;port=5236;dbname=SYSTEM', 'SYSDBA', 'Dameng123');
> \$stmt = \$dbh->query('SELECT COUNT(*) FROM \"gw_etc\".\"admininfo\"');
> echo '表记录数:' . \$stmt->fetchColumn() . PHP_EOL;
> "
表记录数:0
一切正常,刚创的表肯定是没记录
测试一下增删查改是否正常
[root@localhost ~]# vi /tmp/test_crud.php
【文件内容见附录】
[root@localhost ~]# php /tmp/test_crud.php
插入影响行数:1
查询结果:
Array
(
[id] => 4
[admin_id] => test001
[admin_name] => 测试员
[domain_name] => test.domain.com
)
更新影响行数:1
更新后查询结果:
Array
(
[id] => 4
[admin_id] => test001
[admin_name] => 更新测试
[domain_name] => test.domain.com
)
删除影响行数:1
剩余记录数(应等于0):0
用客户相同的测试逻辑
[root@localhost ~]# vi /tmp/reproduce_customer_test.php [root@localhost ~]# php /tmp/reproduce_customer_test.php ======================================== PHP 8.5.8 + 达梦 8.5 驱动 验证测试 ======================================== ✓ PDO 连接成功 ✓ 测试数据插入成功 query() 测试 返回类型: PDOStatement columnCount(): 3 (期望: 3) rowCount(): -1 列元数据 (getColumnMeta): 列 0: id (int) 列 1: admin_id (varchar) 列 2: admin_type (varchar) fetch(PDO::FETCH_ASSOC) 测试: 返回: 数组 Array ( [id] => 3 [admin_id] => test_customer [admin_type] => admin ) fetchAll() 测试: 行数: 1 第1行数据: Array ( [id] => 3 [admin_id] => test_customer [admin_type] => admin ) ======================================== 环境信息 ======================================== PHP 版本: 8.5.8 PDO 驱动: mysql, sqlite, dm 达梦服务器版本: 9.1.0.26
[root@localhost ~]# vi /tmp/test_dm_types.php
【文件内容见附录】
[root@localhost ~]# php /tmp/test_dm_types.php
=== 达梦数据类型测试 ===
0. 清理旧表...
✅ 旧表已删除
1. 创建测试表 type_test...
✅ 表 type_test 创建成功
2. 查看表结构 (DESC)...
列名 | 数据类型 | 长度 | 精度 | 小数位 | 可空
-------------------------------------------------------------------------------------
id | INT | 4 | - | - | 非空
varchar_col | VARCHAR | 100 | - | - | 可空
char_col | CHAR | 20 | - | - | 可空
int_col | INT | 4 | - | - | 可空
bigint_col | BIGINT | 8 | - | - | 可空
decimal_col | DECIMAL | 22 | 18 | 2 | 可空
number_col | NUMBER | 22 | 10 | 3 | 可空
real_col | REAL | 4 | 24 | - | 可空
double_col | DOUBLE | 8 | 53 | - | 可空
float_col | FLOAT | 8 | 53 | - | 可空
date_col | DATE | 3 | - | - | 可空
time_col | TIME | 5 | - | - | 可空
timestamp_col | TIMESTAMP | 8 | - | 6 | 可空
datetime_col | DATETIME | 8 | - | 6 | 可空
blob_col | BLOB | 2147483647 | - | - | 可空
clob_col | CLOB | 2147483647 | - | - | 可空
text_col | TEXT | 2147483647 | - | - | 可空
tinyint_col | TINYINT | 1 | - | - | 可空
smallint_col | SMALLINT | 2 | - | - | 可空
bit_col | BIT | 1 | - | - | 可空
3. 插入测试数据...
✅ 测试数据插入成功
4. 查询数据 (SELECT *)...
字段名 | 值
----------------------------------------------------------------------
id | 1
varchar_col | 测试字符串
char_col | CHAR类型测试
int_col | 12345
bigint_col | 9876543210
decimal_col | 12345.67
number_col | 987.654
real_col | 3.1415901
double_col | 2.718281828
float_col | 1.41421356
date_col | 2026-08-17
time_col | 14:30:25
timestamp_col | 2026-08-17 14:30:25.000000
datetime_col | 2026-08-17 14:30:25.123000
blob_col | BLOB二进制数据测试
clob_col | CLOB大文本内容测试
text_col | TEXT大文本内容测试
tinyint_col | 127
smallint_col | 32767
bit_col | 1
5. 表统计信息...
总行数: 1
✅ 测试完成!
该pdo驱动能在php8.5.8版本上正常使用,增删查改都正常,columnCount()和fetch()也能正常调用,各种类型(clob、blob、double、real、number、decimal、timestamp等)的创建、插入、删除也正常
PHP Fatal error: Unable to start dm module in Unknown on line 0 Stack trace: #0 {main}检查/usr/lib或/usr/lib64/下有没有libdmdpi.so文件,达梦pdo驱动依赖这个库。如果没有,可以在达梦数据库安装目录下的bin文件夹找到,复制到/usr/lib下
或者(临时)设置环境变量
[root@localhost php]# export LD_LIBRARY_PATH=/data/dmdbms/bin:$LD_LIBRARY_PATH
下载链接:
版本标识:releasing-3241-20260814-php-x86_kylin10_sp1_64
版本信息:releasing-3241-20260814-php-x86_kylin10_sp1_64
安装包链接:链接地址:https://eco.dameng.com/s/YHTOZL4I6E提取码:a83x
版本标识:releasing-3241-20260814-php-HWarm920_kylin10_sp1_64
版本信息:releasing-3241-20260814-php-HWarm920_kylin10_sp1_64
安装包链接:链接地址:https://eco.dameng.com/s/QJ11DAOI68提取码:wtrj
<?php
$dbh = new PDO('dm:host=localhost;port=5236;dbname=SYSTEM', 'SYSDBA', 'Dameng123');
// 1. 插入测试数据
$sql = 'INSERT INTO "gw_etc"."admininfo"
("admin_id", "admin_pass", "admin_type", "admin_purview", "admin_name", "admin_desc", "domain_name")
VALUES (\'test001\', \'pass123\', \'admin\', 1, \'测试员\', \'测试描述\', \'test.domain.com\')';
$affected = $dbh->exec($sql);
echo "插入影响行数:" . $affected . "\n";
// 2. 查询刚插入的数据
$stmt = $dbh->query('SELECT "id", "admin_id", "admin_name", "domain_name" FROM "gw_etc"."admininfo" WHERE "admin_id"=\'test001\'');
$row = $stmt->fetch(PDO::FETCH_ASSOC);
echo "查询结果:\n";
print_r($row);
// 3. 更新数据
$sql = 'UPDATE "gw_etc"."admininfo" SET "admin_name"=\'更新测试\' WHERE "admin_id"=\'test001\'';
$affected = $dbh->exec($sql);
echo "更新影响行数:" . $affected . "\n";
// 4. 再次查询验证更新
$stmt = $dbh->query('SELECT "id", "admin_id", "admin_name", "domain_name" FROM "gw_etc"."admininfo" WHERE "admin_id"=\'test001\'');
$row = $stmt->fetch(PDO::FETCH_ASSOC);
echo "更新后查询结果:\n";
print_r($row);
// 5. 删除测试数据
$sql = 'DELETE FROM "gw_etc"."admininfo" WHERE "admin_id"=\'test001\'';
$affected = $dbh->exec($sql);
echo "删除影响行数:" . $affected . "\n";
// 6. 最终验证删除成功
$stmt = $dbh->query('SELECT COUNT(*) FROM "gw_etc"."admininfo" WHERE "admin_id"=\'test001\'');
$count = $stmt->fetchColumn();
echo "剩余记录数(应等于0):" . $count . "\n";
?>
<?php
echo "========================================\n";
echo " PHP 8.5.8 + 达梦 8.5 驱动 验证测试\n";
echo "========================================\n\n";
$dbh = new PDO('dm:host=localhost;port=5236;dbname=SYSTEM', 'SYSDBA', 'Dameng123');
echo "✓ PDO 连接成功\n\n";
// 先插入一条测试数据
$sql = 'INSERT INTO "gw_etc"."admininfo"
("admin_id", "admin_pass", "admin_type", "admin_purview", "admin_name", "admin_desc", "domain_name")
VALUES (\'test_customer\', \'pass123\', \'admin\', 1, \'客户测试\', \'复现测试\', \'test.customer.com\')';
try {
$dbh->exec($sql);
echo "✓ 测试数据插入成功\n\n";
} catch (PDOException $e) {
echo "ℹ 测试数据可能已存在\n\n";
}
// 查询测试
$sql = 'SELECT "id", "admin_id", "admin_type" FROM "gw_etc"."admininfo"';
$stmt = $dbh->query($sql);
echo "query() 测试\n";
echo "返回类型: " . get_class($stmt) . "\n";
echo "columnCount(): " . $stmt->columnCount() . " (期望: 3)\n";
echo "rowCount(): " . $stmt->rowCount() . "\n\n";
// 列元数据
echo "列元数据 (getColumnMeta):\n";
for ($i = 0; $i < $stmt->columnCount(); $i++) {
$meta = $stmt->getColumnMeta($i);
echo " 列 $i: " . $meta['name'] . " (" . $meta['native_type'] . ")\n";
}
echo "\n";
// fetch 测试
echo "fetch(PDO::FETCH_ASSOC) 测试:\n";
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row === false) {
echo " 返回: false (无数据)\n";
} elseif (empty($row)) {
echo " 返回: 空数组\n";
} else {
echo " 返回: 数组\n";
print_r($row);
}
echo "\n";
// fetchAll 测试
echo "fetchAll() 测试:\n";
$stmt = $dbh->query('SELECT "id", "admin_id", "admin_type" FROM "gw_etc"."admininfo"');
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo " 行数: " . count($rows) . "\n";
if (count($rows) > 0) {
echo " 第1行数据:\n";
print_r($rows[0]);
}
echo "\n";
echo "========================================\n";
echo " 环境信息\n";
echo "========================================\n";
echo "PHP 版本: " . PHP_VERSION . "\n";
echo "PDO 驱动: " . implode(", ", PDO::getAvailableDrivers()) . "\n";
echo "达梦服务器版本: " . $dbh->getAttribute(PDO::ATTR_SERVER_VERSION) . "\n";
?>
<?php
$conn = dm_connect("localhost", "SYSDBA", "Dameng123");
if (!$conn) {
die("连接失败: " . dm_error());
}
echo "=== 达梦数据类型测试 ===\n\n";
$table_name = "type_test";
// 1. 删除旧表(如果存在)
echo "0. 清理旧表...\n";
$drop_sql = "DROP TABLE IF EXISTS \"GW_ETC\".\"{$table_name}\" CASCADE";
if (dm_exec($conn, $drop_sql)) {
echo "✅ 旧表已删除\n";
} else {
// 如果表不存在,忽略错误
if (strpos(dm_error(), "无效的表或视图名") !== false) {
echo "✅ 表不存在,跳过删除\n";
} else {
echo "⚠️ 删除表时出现其他错误: " . dm_error() . "\n";
}
}
// 2. 创建测试表
echo "\n1. 创建测试表 {$table_name}...\n";
$create_sql = <<<SQL
CREATE TABLE "GW_ETC"."{$table_name}" (
"id" INT IDENTITY(1, 1) NOT NULL,
"varchar_col" VARCHAR(100),
"char_col" CHAR(20),
"int_col" INT,
"bigint_col" BIGINT,
"decimal_col" DECIMAL(18, 2),
"number_col" NUMBER(10, 3),
"real_col" REAL,
"double_col" DOUBLE,
"float_col" FLOAT,
"date_col" DATE,
"time_col" TIME,
"timestamp_col" TIMESTAMP,
"datetime_col" DATETIME,
"blob_col" BLOB,
"clob_col" CLOB,
"text_col" TEXT,
"tinyint_col" TINYINT,
"smallint_col" SMALLINT,
"bit_col" BIT,
NOT CLUSTER PRIMARY KEY("id")
) STORAGE(ON "MAIN", CLUSTERBTR);
SQL;
if (dm_exec($conn, $create_sql)) {
echo "✅ 表 {$table_name} 创建成功\n";
} else {
echo "❌ 创建表失败: " . dm_error() . "\n";
dm_close($conn);
exit;
}
// 3. 查看表结构 (DESC)
echo "\n2. 查看表结构 (DESC)...\n";
$desc_sql = "SELECT COLUMN_NAME, DATA_TYPE, DATA_LENGTH, DATA_PRECISION, DATA_SCALE, NULLABLE
FROM USER_TAB_COLS WHERE TABLE_NAME = '{$table_name}' ORDER BY COLUMN_ID";
$result = dm_exec($conn, $desc_sql);
if ($result) {
echo sprintf("%-20s | %-15s | %-10s | %-10s | %-8s | %s\n",
"列名", "数据类型", "长度", "精度", "小数位", "可空");
echo str_repeat("-", 85) . "\n";
while ($row = dm_fetch_array($result)) {
echo sprintf("%-20s | %-15s | %-10s | %-10s | %-8s | %s\n",
$row['COLUMN_NAME'],
$row['DATA_TYPE'],
$row['DATA_LENGTH'] ?: '-',
$row['DATA_PRECISION'] ?: '-',
$row['DATA_SCALE'] ?: '-',
$row['NULLABLE'] == 'Y' ? '可空' : '非空'
);
}
dm_free_result($result);
}
// 4. 插入测试数据(BLOB使用HEXTORAW转换)
echo "\n3. 插入测试数据...\n";
// 将字符串转换为十六进制(用于BLOB)
$blob_data = "BLOB二进制数据测试";
$blob_hex = bin2hex($blob_data);
// CLOB和TEXT可以直接插入字符串
$clob_data = "CLOB大文本内容测试";
$text_data = "TEXT大文本内容测试";
$insert_sql = <<<SQL
INSERT INTO "GW_ETC"."{$table_name}" (
"varchar_col", "char_col", "int_col", "bigint_col", "decimal_col", "number_col",
"real_col", "double_col", "float_col",
"date_col", "time_col", "timestamp_col", "datetime_col",
"blob_col", "clob_col", "text_col",
"tinyint_col", "smallint_col", "bit_col"
) VALUES (
'测试字符串', 'CHAR类型测试', 12345, 9876543210, 12345.67, 987.654,
3.14159, 2.718281828, 1.41421356,
DATE '2026-08-17', TIME '14:30:25', TIMESTAMP '2026-08-17 14:30:25', DATETIME '2026-08-17 14:30:25.123',
HEXTORAW('{$blob_hex}'), '{$clob_data}', '{$text_data}',
127, 32767, 1
)
SQL;
if (dm_exec($conn, $insert_sql)) {
echo "✅ 测试数据插入成功\n";
} else {
echo "❌ 插入失败: " . dm_error() . "\n";
echo "SQL: " . $insert_sql . "\n";
}
// 5. 查询数据
echo "\n4. 查询数据 (SELECT *)...\n";
$select_sql = "SELECT * FROM \"GW_ETC\".\"{$table_name}\"";
$result = dm_exec($conn, $select_sql);
if ($result) {
$row = dm_fetch_array($result);
if ($row) {
echo "\n字段名 | 值\n";
echo str_repeat("-", 70) . "\n";
foreach ($row as $key => $value) {
if (is_null($value)) {
$display = "NULL";
} elseif (strlen($value) > 100) {
$display = substr($value, 0, 100) . "...";
} else {
$display = $value;
}
echo sprintf("%-20s | %s\n", $key, $display);
}
} else {
echo "❌ 没有数据\n";
}
dm_free_result($result);
}
// 6. 查看行数
echo "\n5. 表统计信息...\n";
$count_sql = "SELECT COUNT(*) AS total_rows FROM \"GW_ETC\".\"{$table_name}\"";
$result = dm_exec($conn, $count_sql);
if ($result) {
$row = dm_fetch_array($result);
echo "总行数: " . $row['TOTAL_ROWS'] . "\n";
dm_free_result($result);
}
dm_close($conn);
echo "\n✅ 测试完成!\n";
?>
文章
阅读量
获赞
