首页/文章列表/文章详情

ThinkPHP6支持金仓数据库(Kingbase)解决无法使用模型查询问题

编程知识2262024-08-01评论

参考了很多前人的文章,最后只支持Db::query原生查询,不支持thinkphp数据模型方法,这在实际项目中是很难接受的,特分享出解决方案。

先按照流程配置如下:

1.准备工作

首先确认PHP支持金仓数据库的扩展,可以去金仓官网下载,安装配置(详细配置略过……)。

使用 php -m 命令检查,显示有 pdo_kdb即可。 这里注意一下libpq.dll的版本要>=10,否则会报错误。

2,新增金仓数据库的connenter类

进到ThinkPHP项目目录下的vendor\topthink\think-orm\src\db\connector\下,复制Pgsql.php为Kingbase.php(基于pgsql修改),修改文件中的类名为Kingbase。

/**
 * Kingbase数据库驱动
 */
class Kingbase extends PDOConnection

找到 protected function parseDsn(array $config): string 方法,修改该方法下代码:

$dsn = 'pgsql:dbname=' . $config['database'] . ';host=' . $config['hostname'];//修改为:$dsn = 'kdb:host=' . $config['hostname'] . ';dbname=' . $config['database'];

3.新增金仓数据库的builder类

进到ThinkPHP项目目录下的vendor\topthink\think-orm\src\db\builder\下,复制Pgsql.php为Kingbase.php,同样修改文件中的类名为Kingbase。

/** * Kingbase数据库驱动 */class Kingbase extends Builder

其他代码不需要修改。

 

4.ThinkPHP配置文件

三处mysql都修改为kingbase:

return [ // 默认使用的数据库连接配置 'default' => env('database.driver', 'kingbase'),……// 数据库连接配置信息 'connections' => [ 'kingbase' => [ // 数据库类型 'type' => env('database.type', 'kingbase'), // 服务器地址 'hostname' => env('database.hostname', 'localhost'), // 数据库名 'database' => env('database.database', 'TEST'), // 用户名 'username' => env('database.username', 'SYSTEM'), // 密码 'password' => env('database.password', '123456'), // 端口 'hostport' => env('database.hostport', '54321'), // 数据库连接参数 'params' => [], // 数据库编码默认采用utf8 'charset' => env('database.charset', 'utf8'), // 数据库表前缀 'prefix' => env('database.prefix', ''),…… // 更多的数据库配置信息 ],];

到此处,和其他文章介绍的方案都一样,现在介绍重点,重点就在这个执行的sql语句上,这个语句执行了很多次都不成功,不是提示table_msg函数不存在,就是其他的一些错误,后来在KStudio中单独创建各个函数,依次排除问题解决。
现在分享3个函数的创建语句,需要到对应的模式下,新建查询进行导入:

CREATE OR REPLACE FUNCTION public .pgsql_type(a_type  varchar )  RETURNS varchar ASDECLAREv_type  varchar ;BEGIN IF a_type= 'int8' THEN v_type:= 'bigint' ; ELSIF a_type= 'int4' THEN v_type:= 'integer' ; ELSIF a_type= 'int2' THEN v_type:= 'smallint' ; ELSIF a_type= 'bpchar' THEN v_type:= 'char' ;ELSE v_type:=a_type;END IF;RETURN v_type;END

 

CREATE OR REPLACE FUNCTION public .table_msg(a_schema_name  varchar , a_table_name  varchar )  RETURNS SETOF tablestruct  ASDECLAREv_ret  public .tablestruct;v_oid oid;v_sql text;v_rec RECORD;v_key  varchar ;BEGIN SELECT pg_class.oid  INTO v_oid FROM pg_classINNER JOIN pg_namespace  ON ( pg_class.relnamespace = pg_namespace.oid AND lower (pg_namespace.nspname) = a_schema_name ) WHERE pg_class.relname = a_table_name;IF  NOT FOUND  THEN RETURN ;END IF;v_sql =  ' SELECT sys_attribute.attname AS fields_name, sys_attribute.attnum AS fields_index, pgsql_type(sys_type.typname::varchar) AS fields_type, sys_attribute.atttypmod-4 as fields_length, CASE WHEN sys_attribute.attnotnull THEN ' 'not null' ' ELSE ' '' ' END AS fields_not_null, sys_attrdef.adbin AS fields_default, sys_description.description AS fields_comment FROM sys_attribute INNER JOIN sys_class ON sys_attribute.attrelid = sys_class.oid INNER JOIN sys_type ON sys_attribute.atttypid = sys_type.oid LEFT OUTER JOIN sys_attrdef ON sys_attrdef.adrelid = sys_class.oid AND sys_attrdef.adnum = sys_attribute.attnum LEFT OUTER JOIN sys_description ON sys_description.objoid = sys_class.oid AND sys_description.objsubid = sys_attribute.attnum WHERE sys_attribute.attnum > 0 AND attisdropped <> ATTISLOCAL ORDER BY sys_attribute.attnum' ;FOR v_rec  IN EXECUTE v_sql LOOP v_ret.fields_name = v_rec.fields_name;v_ret.fields_type = v_rec.fields_type;IF v_rec.fields_length > 0  THEN v_ret.fields_length := v_rec.fields_length;ELSE v_ret.fields_length :=  NULL ;END IF;v_ret.fields_not_null = v_rec.fields_not_null;v_ret.fields_default = v_rec.fields_default;v_ret.fields_comment = v_rec.fields_comment;SELECT constraint_name  INTO v_keyFROM information_schema.key_column_usageWHERE table_schema = a_schema_name AND table_name = a_table_name AND column_name = v_rec.fields_name;IF FOUND  THEN v_ret.fields_key_name = v_key;ELSE v_ret.fields_key_name =  '' ;END IF;RETURN NEXT v_ret;END LOOP;RETURN ;END

  

CREATE OR REPLACE FUNCTION public .table_msg(a_table_name  varchar )  RETURNS SETOF tablestruct  ASDECLAREv_ret tablestruct;BEGINFOR v_ret  IN SELECT *  FROM table_msg( 'public' ,a_table_name) LOOP RETURN NEXT v_ret;END LOOP; RETURN ;END

 

成功导入3个函数后,在函数项下会出现3个函数,如图:

 

在数据类型功能下,增加一个数据类型,数据类型配置如下:

 

 

完成此步骤后:可以在Controller控制器中执行如下代码测试:

 

try { $data =\app\home\model\User::select(); dump( $data ); } catch (\Exception  $e ) { dump( $e ->getMessage()); } \app\home\model\User::create(["user_name" =>"123456" ,"user_pwd" =>"123456" ,"mobile" =>"abc" ,"full_name" =>"abc" , ]);

  

 

博客园

这个人很懒...

用户评论 (0)

发表评论

captcha