2023-06-24 18:37:52 +00:00
< ? php
namespace ba ;
2024-02-26 13:34:15 +00:00
use Throwable ;
2023-06-24 18:37:52 +00:00
use think\facade\Db ;
use think\facade\Config ;
2023-06-29 06:37:04 +00:00
use think\migration\db\Table ;
2023-06-24 18:37:52 +00:00
use Phinx\Db\Adapter\AdapterFactory ;
use Phinx\Db\Adapter\AdapterInterface ;
/**
* 数据表管理类
*/
class TableManager
{
/**
* 返回一个 Phinx / Db / Table 实例 用于操作数据表
2024-02-25 17:18:16 +00:00
* @ param string $table 表名
* @ param array $options 传递给 Phinx / Db / Table 的 options
* @ param bool $prefixWrapper 是否使用表前缀包装表名
* @ param ? string $connection 连接配置标识
2023-06-24 18:37:52 +00:00
* @ return Table
2024-02-26 15:11:51 +00:00
* @ throws Throwable
2023-06-24 18:37:52 +00:00
*/
2024-02-25 20:05:04 +00:00
public static function phinxTable ( string $table , array $options = [], bool $prefixWrapper = true , ? string $connection = null ) : Table
2023-06-24 18:37:52 +00:00
{
2024-02-25 20:05:04 +00:00
return new Table ( $table , $options , self :: phinxAdapter ( $prefixWrapper , $connection ));
2023-06-29 06:37:04 +00:00
}
/**
2024-02-25 20:05:04 +00:00
* 返回 Phinx\Db\Adapter\AdapterFactory (适配器 / 连接驱动)实例
2024-02-25 17:18:16 +00:00
* @ param bool $prefixWrapper 是否使用表前缀包装表名
* @ param ? string $connection 连接配置标识
2023-06-29 06:37:04 +00:00
* @ return AdapterInterface
2024-02-26 15:11:51 +00:00
* @ throws Throwable
2023-06-29 06:37:04 +00:00
*/
2024-02-25 20:05:04 +00:00
public static function phinxAdapter ( bool $prefixWrapper = true , ? string $connection = null ) : AdapterInterface
2023-06-29 06:37:04 +00:00
{
2024-02-25 20:05:04 +00:00
$config = static :: getPhinxDbConfig ( $connection );
$factory = AdapterFactory :: instance ();
$adapter = $factory -> getAdapter ( $config [ 'adapter' ], $config );
if ( $prefixWrapper ) return $factory -> getWrapper ( 'prefix' , $adapter );
return $adapter ;
2023-06-29 06:37:04 +00:00
}
2023-06-24 18:37:52 +00:00
2023-06-29 06:37:04 +00:00
/**
2024-02-25 20:05:04 +00:00
* 数据表名
* @ param string $table 表名,带不带前缀均可
* @ param bool $fullName 是否返回带前缀的表名
2024-02-25 17:18:16 +00:00
* @ param ? string $connection 连接配置标识
2024-02-25 20:05:04 +00:00
* @ return string 表名
* @ throws Exception
2023-06-29 06:37:04 +00:00
*/
2024-02-25 20:05:04 +00:00
public static function tableName ( string $table , bool $fullName = true , ? string $connection = null ) : string
2023-06-29 06:37:04 +00:00
{
2024-02-26 15:11:51 +00:00
$connection = self :: getConnectionConfig ( $connection );
$pattern = '/^' . $connection [ 'prefix' ] . '/i' ;
2024-02-25 20:05:04 +00:00
return ( $fullName ? $connection [ 'prefix' ] : '' ) . ( preg_replace ( $pattern , '' , $table ));
2023-06-29 06:37:04 +00:00
}
2024-02-26 12:45:12 +00:00
/**
* 数据表列表
* @ param ? string $connection 连接配置标识
* @ throws Exception
*/
public static function getTableList ( ? string $connection = null ) : array
{
$tableList = [];
2024-04-16 19:32:21 +00:00
$config = self :: getConnectionConfig ( $connection );
$connection = self :: getConnection ( $connection );
$tables = Db :: connect ( $connection ) -> query ( " SELECT TABLE_NAME,TABLE_COMMENT FROM information_schema.TABLES WHERE table_schema = ? " , [ $config [ 'database' ]]);
2024-02-26 12:45:12 +00:00
foreach ( $tables as $row ) {
$tableList [ $row [ 'TABLE_NAME' ]] = $row [ 'TABLE_NAME' ] . ( $row [ 'TABLE_COMMENT' ] ? ' - ' . $row [ 'TABLE_COMMENT' ] : '' );
}
return $tableList ;
}
2024-02-26 13:34:15 +00:00
/**
* 获取数据表所有列
* @ param string $table 数据表名
* @ param bool $onlyCleanComment 只要干净的字段注释信息
* @ param ? string $connection 连接配置标识
* @ throws Throwable
*/
public static function getTableColumns ( string $table , bool $onlyCleanComment = false , ? string $connection = null ) : array
{
if ( ! $table ) return [];
2024-02-26 15:11:51 +00:00
$table = self :: tableName ( $table , true , $connection );
2024-04-16 19:32:21 +00:00
$config = self :: getConnectionConfig ( $connection );
$connection = self :: getConnection ( $connection );
2024-02-26 13:34:15 +00:00
// 从数据库中获取表字段信息
// Phinx 目前无法正确获取到列注释信息,故使用 sql
$sql = " SELECT * FROM `information_schema`.`columns` "
. " WHERE TABLE_SCHEMA = ? AND table_name = ? "
. " ORDER BY ORDINAL_POSITION " ;
2024-04-16 19:32:21 +00:00
$columnList = Db :: connect ( $connection ) -> query ( $sql , [ $config [ 'database' ], $table ]);
2024-02-26 13:34:15 +00:00
$fieldList = [];
foreach ( $columnList as $item ) {
if ( $onlyCleanComment ) {
$fieldList [ $item [ 'COLUMN_NAME' ]] = '' ;
if ( $item [ 'COLUMN_COMMENT' ]) {
$comment = explode ( ':' , $item [ 'COLUMN_COMMENT' ]);
$fieldList [ $item [ 'COLUMN_NAME' ]] = $comment [ 0 ];
}
continue ;
}
$fieldList [ $item [ 'COLUMN_NAME' ]] = $item ;
}
return $fieldList ;
}
2023-06-29 06:37:04 +00:00
/**
2024-02-25 20:05:04 +00:00
* 系统是否存在多个数据库连接配置
2023-06-29 06:37:04 +00:00
*/
2024-02-25 20:05:04 +00:00
public static function isMultiDatabase () : bool
{
return count ( Config :: get ( " database.connections " )) > 1 ;
}
/**
* 获取数据库连接配置标识
* @ param ? string $source
* @ return string 连接配置标识
*/
public static function getConnection ( ? string $source = null ) : string
2023-06-29 06:37:04 +00:00
{
2024-02-28 16:28:06 +00:00
if ( ! $source || $source === 'default' ) {
2024-02-25 20:05:04 +00:00
return Config :: get ( 'database.default' );
}
return $source ;
2023-06-24 18:37:52 +00:00
}
2024-02-26 15:11:51 +00:00
/**
2024-02-28 16:28:06 +00:00
* 获取某个数据库连接的配置数组
2024-02-26 15:11:51 +00:00
* @ param ? string $connection 连接配置标识
* @ throws Exception
*/
public static function getConnectionConfig ( ? string $connection = null ) : array
{
$connection = self :: getConnection ( $connection );
$connection = config ( " database.connections. $connection " );
if ( ! is_array ( $connection )) {
throw new Exception ( 'Database connection configuration error' );
}
// 分布式
if ( $connection [ 'deploy' ] == 1 ) {
$keys = [ 'type' , 'hostname' , 'database' , 'username' , 'password' , 'hostport' , 'charset' , 'prefix' ];
foreach ( $connection as $key => $item ) {
if ( in_array ( $key , $keys )) {
$connection [ $key ] = is_array ( $item ) ? $item [ 0 ] : explode ( ',' , $item )[ 0 ];
}
}
}
return $connection ;
}
2023-06-24 18:37:52 +00:00
/**
2024-02-25 20:05:04 +00:00
* 获取 Phinx 适配器需要的数据库配置
2024-02-25 17:18:16 +00:00
* @ param ? string $connection 连接配置标识
2023-06-24 18:37:52 +00:00
* @ return array
2024-02-26 15:11:51 +00:00
* @ throws Throwable
2023-06-24 18:37:52 +00:00
*/
2024-02-25 20:05:04 +00:00
protected static function getPhinxDbConfig ( ? string $connection = null ) : array
2023-06-24 18:37:52 +00:00
{
2024-02-26 15:11:51 +00:00
$config = self :: getConnectionConfig ( $connection );
2024-02-25 17:18:16 +00:00
$connection = self :: getConnection ( $connection );
2024-02-25 20:05:04 +00:00
$db = Db :: connect ( $connection );
// 数据库为懒连接,执行 sql 命令为 $db 实例连接数据库
$db -> query ( 'SELECT 1' );
2023-06-24 18:37:52 +00:00
$table = Config :: get ( 'database.migration_table' , 'migrations' );
2024-02-26 15:11:51 +00:00
return [
'adapter' => $config [ 'type' ],
'connection' => $db -> getPdo (),
'name' => $config [ 'database' ],
'table_prefix' => $config [ 'prefix' ],
'migration_table' => $config [ 'prefix' ] . $table ,
];
2023-06-24 18:37:52 +00:00
}
}