@@ -118,34 +118,99 @@ protected function createModel($class, $namespace, $file, $connection = null)
118118 try {
119119 $ prefix = config ("database.connections. $ connection.prefix " ) ?? '' ;
120120 $ database = config ("database.connections. $ connection.database " );
121+ $ driver = config ("database.connections. $ connection.driver " ) ?? 'mysql ' ;
121122 $ inflector = InflectorFactory::create ()->build ();
122123 $ table_plura = $ inflector ->pluralize ($ inflector ->tableize ($ class ));
123124 $ con = Db::connection ($ connection );
124- if ($ con ->select ("show tables like ' {$ prefix }{$ table_plura }' " )) {
125- $ table_val = "' $ table' " ;
126- $ table = "{$ prefix }{$ table_plura }" ;
127- } else if ($ con ->select ("show tables like ' {$ prefix }{$ table }' " )) {
128- $ table_val = "' $ table' " ;
129- $ table = "{$ prefix }{$ table }" ;
130- }
131- $ tableComment = $ con ->select ('SELECT table_comment FROM information_schema.`TABLES` WHERE table_schema = ? AND table_name = ? ' , [$ database , $ table ]);
132- if (!empty ($ tableComment )) {
133- $ comments = $ tableComment [0 ]->table_comment ?? $ tableComment [0 ]->TABLE_COMMENT ;
134- $ properties .= " * {$ table } {$ comments }" . PHP_EOL ;
125+
126+ // 检查表是否存在(兼容MySQL和PostgreSQL)
127+ if ($ driver === 'pgsql ' ) {
128+ // PostgreSQL 表检查
129+ $ schema = config ("database.connections. $ connection.schema " ) ?? 'public ' ;
130+ $ exists_plura = $ con ->select ("SELECT to_regclass(' {$ schema }. {$ prefix }{$ table_plura }') as table_exists " );
131+ $ exists = $ con ->select ("SELECT to_regclass(' {$ schema }. {$ prefix }{$ table }') as table_exists " );
132+
133+ if (!empty ($ exists_plura [0 ]->table_exists )) {
134+ $ table_val = "' $ table' " ;
135+ $ table = "{$ prefix }{$ table_plura }" ;
136+ } else if (!empty ($ exists [0 ]->table_exists )) {
137+ $ table_val = "' $ table' " ;
138+ $ table = "{$ prefix }{$ table }" ;
139+ }
140+ } else {
141+ // MySQL 表检查
142+ if ($ con ->select ("show tables like ' {$ prefix }{$ table_plura }' " )) {
143+ $ table_val = "' $ table' " ;
144+ $ table = "{$ prefix }{$ table_plura }" ;
145+ } else if ($ con ->select ("show tables like ' {$ prefix }{$ table }' " )) {
146+ $ table_val = "' $ table' " ;
147+ $ table = "{$ prefix }{$ table }" ;
148+ }
135149 }
136- foreach ($ con ->select ("select COLUMN_NAME,DATA_TYPE,COLUMN_KEY,COLUMN_COMMENT from INFORMATION_SCHEMA.COLUMNS where table_name = ' $ table' and table_schema = ' $ database' ORDER BY ordinal_position " ) as $ item ) {
137- if ($ item ->COLUMN_KEY === 'PRI ' ) {
138- $ pk = $ item ->COLUMN_NAME ;
139- $ item ->COLUMN_COMMENT .= "(主键) " ;
150+
151+ // 获取表注释和列信息(兼容MySQL和PostgreSQL)
152+ if ($ driver === 'pgsql ' ) {
153+ // PostgreSQL 表注释
154+ $ schema = config ("database.connections. $ connection.schema " ) ?? 'public ' ;
155+ $ tableComment = $ con ->select ("SELECT obj_description(' {$ schema }. {$ table }'::regclass) as table_comment " );
156+ if (!empty ($ tableComment ) && !empty ($ tableComment [0 ]->table_comment )) {
157+ $ comments = $ tableComment [0 ]->table_comment ;
158+ $ properties .= " * {$ table } {$ comments }" . PHP_EOL ;
140159 }
141- $ type = $ this ->getType ($ item ->DATA_TYPE );
142- if ($ item ->COLUMN_NAME === 'created_at ' ) {
143- $ hasCreatedAt = true ;
160+
161+ // PostgreSQL 列信息
162+ $ columns = $ con ->select ("
163+ SELECT
164+ a.attname as column_name,
165+ format_type(a.atttypid, a.atttypmod) as data_type,
166+ CASE WHEN con.contype = 'p' THEN 'PRI' ELSE '' END as column_key,
167+ d.description as column_comment
168+ FROM pg_catalog.pg_attribute a
169+ LEFT JOIN pg_catalog.pg_description d ON d.objoid = a.attrelid AND d.objsubid = a.attnum
170+ LEFT JOIN pg_catalog.pg_constraint con ON con.conrelid = a.attrelid AND a.attnum = ANY(con.conkey) AND con.contype = 'p'
171+ WHERE a.attrelid = ' {$ schema }. {$ table }'::regclass
172+ AND a.attnum > 0 AND NOT a.attisdropped
173+ ORDER BY a.attnum
174+ " );
175+
176+ foreach ($ columns as $ item ) {
177+ if ($ item ->column_key === 'PRI ' ) {
178+ $ pk = $ item ->column_name ;
179+ $ item ->column_comment = ($ item ->column_comment ? $ item ->column_comment . ' ' : '' ) . "(主键) " ;
180+ }
181+ $ type = $ this ->getType ($ item ->data_type );
182+ if ($ item ->column_name === 'created_at ' ) {
183+ $ hasCreatedAt = true ;
184+ }
185+ if ($ item ->column_name === 'updated_at ' ) {
186+ $ hasUpdatedAt = true ;
187+ }
188+ $ properties .= " * @property $ type \${$ item ->column_name } " . ($ item ->column_comment ?? '' ) . "\n" ;
144189 }
145- if ($ item ->COLUMN_NAME === 'updated_at ' ) {
146- $ hasUpdatedAt = true ;
190+
191+ } else {
192+ // MySQL 表注释
193+ $ tableComment = $ con ->select ('SELECT table_comment FROM information_schema.`TABLES` WHERE table_schema = ? AND table_name = ? ' , [$ database , $ table ]);
194+ if (!empty ($ tableComment )) {
195+ $ comments = $ tableComment [0 ]->table_comment ?? $ tableComment [0 ]->TABLE_COMMENT ;
196+ $ properties .= " * {$ table } {$ comments }" . PHP_EOL ;
197+ }
198+
199+ // MySQL 列信息
200+ foreach ($ con ->select ("select COLUMN_NAME,DATA_TYPE,COLUMN_KEY,COLUMN_COMMENT from INFORMATION_SCHEMA.COLUMNS where table_name = ' $ table' and table_schema = ' $ database' ORDER BY ordinal_position " ) as $ item ) {
201+ if ($ item ->COLUMN_KEY === 'PRI ' ) {
202+ $ pk = $ item ->COLUMN_NAME ;
203+ $ item ->COLUMN_COMMENT .= "(主键) " ;
204+ }
205+ $ type = $ this ->getType ($ item ->DATA_TYPE );
206+ if ($ item ->COLUMN_NAME === 'created_at ' ) {
207+ $ hasCreatedAt = true ;
208+ }
209+ if ($ item ->COLUMN_NAME === 'updated_at ' ) {
210+ $ hasUpdatedAt = true ;
211+ }
212+ $ properties .= " * @property $ type \${$ item ->COLUMN_NAME } {$ item ->COLUMN_COMMENT }\n" ;
147213 }
148- $ properties .= " * @property $ type \${$ item ->COLUMN_NAME } {$ item ->COLUMN_COMMENT }\n" ;
149214 }
150215 } catch (\Throwable $ e ) {
151216 echo $ e ->getMessage () . PHP_EOL ;
@@ -223,31 +288,89 @@ protected function createTpModel($class, $namespace, $file, $connection = null)
223288 $ config_name = $ is_thinkorm_v2 ? 'think-orm ' : 'thinkorm ' ;
224289 $ prefix = config ("$ config_name.connections. $ connection.prefix " ) ?? '' ;
225290 $ database = config ("$ config_name.connections. $ connection.database " );
291+ $ driver = config ("$ config_name.connections. $ connection.type " ) ?? 'mysql ' ;
292+
226293 if ($ is_thinkorm_v2 ) {
227294 $ con = \support \think \Db::connect ($ connection );
228295 } else {
229296 $ con = \think \facade \Db::connect ($ connection );
230297 }
231298
232- if ($ con ->query ("show tables like ' {$ prefix }{$ table }' " )) {
233- $ table = "{$ prefix }{$ table }" ;
234- $ table_val = "' $ table' " ;
235- } else if ($ con ->query ("show tables like ' {$ prefix }{$ table }s' " )) {
236- $ table = "{$ prefix }{$ table }s " ;
237- $ table_val = "' $ table' " ;
238- }
239- $ tableComment = $ con ->query ('SELECT table_comment FROM information_schema.`TABLES` WHERE table_schema = ? AND table_name = ? ' , [$ database , $ table ]);
240- if (!empty ($ tableComment )) {
241- $ comments = $ tableComment [0 ]['table_comment ' ] ?? $ tableComment [0 ]['TABLE_COMMENT ' ];
242- $ properties .= " * {$ table } {$ comments }" . PHP_EOL ;
299+ // 检查表是否存在(兼容MySQL和PostgreSQL)
300+ if ($ driver === 'pgsql ' ) {
301+ // PostgreSQL 表检查
302+ $ schema = config ("$ config_name.connections. $ connection.schema " ) ?? 'public ' ;
303+ $ exists = $ con ->query ("SELECT to_regclass(' {$ schema }. {$ prefix }{$ table }') as table_exists " );
304+ $ exists_plural = $ con ->query ("SELECT to_regclass(' {$ schema }. {$ prefix }{$ table }s') as table_exists " );
305+
306+ if (!empty ($ exists [0 ]['table_exists ' ])) {
307+ $ table = "{$ prefix }{$ table }" ;
308+ $ table_val = "' $ table' " ;
309+ } else if (!empty ($ exists_plural [0 ]['table_exists ' ])) {
310+ $ table = "{$ prefix }{$ table }s " ;
311+ $ table_val = "' $ table' " ;
312+ }
313+ } else {
314+ // MySQL 表检查
315+ if ($ con ->query ("show tables like ' {$ prefix }{$ table }' " )) {
316+ $ table = "{$ prefix }{$ table }" ;
317+ $ table_val = "' $ table' " ;
318+ } else if ($ con ->query ("show tables like ' {$ prefix }{$ table }s' " )) {
319+ $ table = "{$ prefix }{$ table }s " ;
320+ $ table_val = "' $ table' " ;
321+ }
243322 }
244- foreach ($ con ->query ("select COLUMN_NAME,DATA_TYPE,COLUMN_KEY,COLUMN_COMMENT from INFORMATION_SCHEMA.COLUMNS where table_name = ' $ table' and table_schema = ' $ database' ORDER BY ordinal_position " ) as $ item ) {
245- if ($ item ['COLUMN_KEY ' ] === 'PRI ' ) {
246- $ pk = $ item ['COLUMN_NAME ' ];
247- $ item ['COLUMN_COMMENT ' ] .= "(主键) " ;
323+
324+ // 获取表注释和列信息(兼容MySQL和PostgreSQL)
325+ if ($ driver === 'pgsql ' ) {
326+ // PostgreSQL 表注释
327+ $ schema = config ("$ config_name.connections. $ connection.schema " ) ?? 'public ' ;
328+ $ tableComment = $ con ->query ("SELECT obj_description(' {$ schema }. {$ table }'::regclass) as table_comment " );
329+ if (!empty ($ tableComment ) && !empty ($ tableComment [0 ]['table_comment ' ])) {
330+ $ comments = $ tableComment [0 ]['table_comment ' ];
331+ $ properties .= " * {$ table } {$ comments }" . PHP_EOL ;
332+ }
333+
334+ // PostgreSQL 列信息
335+ $ columns = $ con ->query ("
336+ SELECT
337+ a.attname as column_name,
338+ format_type(a.atttypid, a.atttypmod) as data_type,
339+ CASE WHEN con.contype = 'p' THEN 'PRI' ELSE '' END as column_key,
340+ d.description as column_comment
341+ FROM pg_catalog.pg_attribute a
342+ LEFT JOIN pg_catalog.pg_description d ON d.objoid = a.attrelid AND d.objsubid = a.attnum
343+ LEFT JOIN pg_catalog.pg_constraint con ON con.conrelid = a.attrelid AND a.attnum = ANY(con.conkey) AND con.contype = 'p'
344+ WHERE a.attrelid = ' {$ schema }. {$ table }'::regclass
345+ AND a.attnum > 0 AND NOT a.attisdropped
346+ ORDER BY a.attnum
347+ " );
348+
349+ foreach ($ columns as $ item ) {
350+ if ($ item ['column_key ' ] === 'PRI ' ) {
351+ $ pk = $ item ['column_name ' ];
352+ $ item ['column_comment ' ] = ($ item ['column_comment ' ] ? $ item ['column_comment ' ] . ' ' : '' ) . "(主键) " ;
353+ }
354+ $ type = $ this ->getType ($ item ['data_type ' ]);
355+ $ properties .= " * @property $ type \${$ item ['column_name ' ]} " . ($ item ['column_comment ' ] ?? '' ) . "\n" ;
356+ }
357+ } else {
358+ // MySQL 表注释
359+ $ tableComment = $ con ->query ('SELECT table_comment FROM information_schema.`TABLES` WHERE table_schema = ? AND table_name = ? ' , [$ database , $ table ]);
360+ if (!empty ($ tableComment )) {
361+ $ comments = $ tableComment [0 ]['table_comment ' ] ?? $ tableComment [0 ]['TABLE_COMMENT ' ];
362+ $ properties .= " * {$ table } {$ comments }" . PHP_EOL ;
363+ }
364+
365+ // MySQL 列信息
366+ foreach ($ con ->query ("select COLUMN_NAME,DATA_TYPE,COLUMN_KEY,COLUMN_COMMENT from INFORMATION_SCHEMA.COLUMNS where table_name = ' $ table' and table_schema = ' $ database' ORDER BY ordinal_position " ) as $ item ) {
367+ if ($ item ['COLUMN_KEY ' ] === 'PRI ' ) {
368+ $ pk = $ item ['COLUMN_NAME ' ];
369+ $ item ['COLUMN_COMMENT ' ] .= "(主键) " ;
370+ }
371+ $ type = $ this ->getType ($ item ['DATA_TYPE ' ]);
372+ $ properties .= " * @property $ type \${$ item ['COLUMN_NAME ' ]} {$ item ['COLUMN_COMMENT ' ]}\n" ;
248373 }
249- $ type = $ this ->getType ($ item ['DATA_TYPE ' ]);
250- $ properties .= " * @property $ type \${$ item ['COLUMN_NAME ' ]} {$ item ['COLUMN_COMMENT ' ]}\n" ;
251374 }
252375 } catch (\Throwable $ e ) {
253376 echo $ e ;
@@ -303,6 +426,15 @@ protected function getType(string $type)
303426 if (strpos ($ type , 'int ' ) !== false ) {
304427 return 'integer ' ;
305428 }
429+
430+ if (strpos ($ type , 'character varying ' ) !== false || strpos ($ type , 'varchar ' ) !== false ) {
431+ return 'string ' ;
432+ }
433+
434+ if (strpos ($ type , 'timestamp ' ) !== false ) {
435+ return 'string ' ;
436+ }
437+
306438 switch ($ type ) {
307439 case 'varchar ' :
308440 case 'string ' :
@@ -314,11 +446,23 @@ protected function getType(string $type)
314446 case 'datetime ' :
315447 case 'decimal ' :
316448 case 'enum ' :
449+ case 'character ' : // PostgreSQL类型
450+ case 'char ' : // PostgreSQL类型
451+ case 'json ' : // PostgreSQL类型
452+ case 'jsonb ' : // PostgreSQL类型
453+ case 'uuid ' : // PostgreSQL类型
454+ case 'timestamptz ' : // PostgreSQL类型
455+ case 'citext ' : // PostgreSQL类型
317456 return 'string ' ;
318457 case 'boolean ' :
458+ case 'bool ' : // PostgreSQL类型
319459 return 'integer ' ;
320460 case 'float ' :
461+ case 'float4 ' : // PostgreSQL类型 (real)
462+ case 'float8 ' : // PostgreSQL类型 (double precision)
321463 return 'float ' ;
464+ case 'numeric ' : // PostgreSQL类型
465+ return 'string ' ;
322466 default :
323467 return 'mixed ' ;
324468 }
0 commit comments