易于使用的 PHP 包用于更新应用程序的数据库架构并在版本之间迁移数据。
composer req aimeos/upscheme
目录
迁移就像数据库的版本控制。它们允许您在每次安装中获得完全相同的状态。使用 Upscheme,您可以获得:
以下是表格定义的示例,只要您的表格布局必须更改,您就可以调整该定义。然后,Upscheme 将自动添加和修改现有的列和表属性(但出于安全原因不要删除任何内容):
$ this -> db ()-> table ( ' test ' , function ( $ t ) {
$ t -> engine = ' InnoDB ' ;
$ t -> id ();
$ t -> string ( ' domain ' , 32 );
$ t -> string ( ' code ' , 64 )-> opt ( ' charset ' , ' binary ' , [ ' mariadb ' , ' mysql ' ] );
$ t -> string ( ' label ' , 255 );
$ t -> int ( ' pos ' )-> default ( 0 );
$ t -> smallint ( ' status ' );
$ t -> default ();
$ t -> unique ( [ ' domain ' , ' code ' ] );
$ t -> index ( [ ' status ' , ' pos ' ] );
} );
对于升级关系数据库模式,目前最常使用两个包:Doctrine DBAL 和 Doctrine 迁移。虽然 Doctrine DBAL 在抽象几种数据库实现的差异方面做得很好,但它的 API 需要编写大量代码。其他站点上的 Doctrine 迁移有一些缺点,这使得它很难在所有支持第 3 方扩展的应用程序中使用。
DBAL 的 API 非常冗长,即使是简单的事情也需要编写大量代码。 Upscheme 使用 Doctrine DBAL 提供易于使用的 API,用于以最少的代码升级应用程序的数据库模式。对于上面的 Upscheme 示例,这些代码行与迁移中的 DBAL 等效:
$ dbalManager = $ conn -> createSchemaManager ();
$ from = $ manager -> createSchema ();
$ to = $ manager -> createSchema ();
if ( $ to -> hasTable ( ' test ' ) ) {
$ table = $ to -> getTable ( ' test ' );
} else {
$ table = $ to -> createTable ( ' test ' );
}
$ table -> addOption ( ' engine ' , ' InnoDB ' );
$ table -> addColumn ( ' id ' , ' integer ' , [ ' autoincrement ' => true ] );
$ table -> addColumn ( ' domain ' , ' string ' , [ ' length ' => 32 ] );
$ platform = $ conn -> getDatabasePlatform ();
if ( $ platform instanceof Doctrine DBAL Platform MySQLPlatform
|| $ platform instanceof Doctrine DBAL Platform MariaDBPlatform
) {
$ table -> addColumn ( ' code ' , ' string ' , [ ' length ' => 64 , ' customSchemaOptions ' => [ ' charset ' => ' binary ' ]] );
} else {
$ table -> addColumn ( ' code ' , ' string ' , [ ' length ' => 64 ]] );
}
$ table -> addColumn ( ' label ' , ' string ' , [ ' length ' => 255 ] );
$ table -> addColumn ( ' pos ' , ' integer ' , [ ' default ' => 0 ] );
$ table -> addColumn ( ' status ' , ' smallint ' , [] );
$ table -> addColumn ( ' mtime ' , ' datetime ' , [] );
$ table -> addColumn ( ' ctime ' , ' datetime ' , [] );
$ table -> addColumn ( ' editor ' , ' string ' , [ ' length ' => 255 ] );
$ table -> setPrimaryKey ( [ ' id ' ] );
$ table -> addUniqueIndex ( [ ' domain ' , ' code ' ] );
$ table -> addIndex ( [ ' status ' , ' pos ' ] );
foreach ( $ from -> getMigrateToSql ( $ to , $ conn -> getDatabasePlatform () ) as $ sql ) {
$ conn -> executeStatement ( $ sql );
}
Doctrine Migration 依赖于在创建迁移类时命名的迁移类,以确保一定的顺序。此外,它还将已执行的迁移存储在数据库的表中。由此产生了三个主要问题:
down()
时数据丢失如果您的应用程序支持第 3 方扩展,这些扩展可能会向现有表添加列并自行迁移数据。由于无法定义迁移之间的依赖关系,因此几乎不可能在具有多个第三方扩展的应用程序中运行迁移而不发生冲突。为了避免这种情况,Upscheme 在每个迁移任务中提供了易于使用的before()
和after()
方法,其中任务可以定义其对其他任务的依赖关系。
由于 Doctrine Migrations 使用数据库表来记录已执行的迁移,因此如果出现问题,这些记录很容易不同步。相反,Upscheme 仅依赖于实际架构,因此可以从任何状态升级,无论之前发生了什么。
Doctrine Migrations 还支持down()
方法中的反向操作,因此您可以回滚迁移,而 Upscheme 则不支持。经验表明,回滚迁移通常是不可能的,例如在添加新列、迁移现有列的数据并随后删除旧列之后。如果数据迁移是有损的,则无法在down()
方法中重新创建相同的状态。如果您删除了一张桌子,情况也是如此。因此Upscheme只提供方案升级,不提供方案降级,以避免隐式数据丢失。
Upscheme 使用 Doctrine DBAL 从不同的数据库服务器实现中进行抽象。 DBAL 支持所有主要的关系数据库管理系统 (RDBMS),但对可用功能的支持级别不同:
良好的支持:
有限支持:
使用composer安装了aimeos/upscheme
包后,您可以使用Up
类来执行迁移任务:
$ config = [
' driver ' => ' pdo_mysql ' ,
' host ' => ' 127.0.0.1 ' ,
' dbname ' => ' <database> ' ,
' user ' => ' <dbuser> ' ,
' password ' => ' <secret> '
];
Aimeos Upscheme Up:: use ( $ config , ' src/migrations ' )-> up ();
Up::use()
方法需要两个参数:数据库配置和迁移任务的路径。对于配置,驱动程序的数组键和值必须受 Doctrine DBAL 支持。可用的驱动程序有:
有些数据库需要不同的参数,最著名的是 SQLite 和 Oracle:
SQLite:
$ config = [
' driver ' => ' pdo_sqlite ' ,
' path ' => ' path/to/file.sq3 '
];
甲骨文:
$ config = [
' driver ' => ' pdo_oci ' ,
' host ' => ' <host or IP> ' ,
' dbname ' => ' <SID or service name (Oracle 18+)> ' ,
' service ' => true , // for Oracle 18 + only
' user ' => ' <dbuser> ' ,
' password ' => ' <secret> '
];
如果您之前没有使用过 Doctrine DBAL,您的数据库配置可能具有不同的结构和/或对数据库类型使用不同的值。 Upscheme 允许您注册一个自定义方法,将您的配置转换为有效的 DBAL 设置,例如:
Aimeos Upscheme Up:: macro ( ' connect ' , function ( array $ cfg ) {
return Doctrine DBAL DriverManager:: getConnection ( [
' driver ' => $ cfg [ ' adapter ' ],
' host ' => $ cfg [ ' host ' ],
' dbname ' => $ cfg [ ' database ' ],
' user ' => $ cfg [ ' username ' ],
' password ' => $ cfg [ ' password ' ]
] );
} );
Upscheme 还支持多种数据库连接,您可以通过它们的键名称来区分它们:
$ config = [
' db ' => [
' driver ' => ' pdo_mysql ' ,
' host ' => ' 127.0.0.1 ' ,
' dbname ' => ' <database> ' ,
' user ' => ' <dbuser> ' ,
' password ' => ' <secret> '
],
' temp ' => [
' driver ' => ' pdo_sqlite ' ,
' path ' => ' /tmp/mydb.sqlite '
]
];
Aimeos Upscheme Up:: use ( $ config , ' src/migrations ' )-> up ();
当然,你也可以向Up
类传递几种迁移路径:
Aimeos Upscheme Up:: use ( $ config , [ ' src/migrations ' , ' ext/migrations ' ] )-> up ();
要启用(调试)输出,请使用 verbose() 方法:
Aimeos Upscheme Up:: use ( $ config , ' src/migrations ' )-> verbose ()-> up (); // most important only
Aimeos Upscheme Up:: use ( $ config , ' src/migrations ' )-> verbose ( ' vv ' )-> up (); // more verbose
Aimeos Upscheme Up:: use ( $ config , ' src/migrations ' )-> verbose ( ' vvv ' )-> up (); // debugging
迁移任务只需要实现up()
方法,并且必须存储在传递给Up
类的目录之一中:
<?php
namespace Aimeos Upscheme Task ;
use Aimeos Upscheme Schema Table ;
return new class ( $ this ) extends Base {
public function up ()
{
$ this -> db ()-> table ( ' test ' , function ( Table $ t ) {
$ t -> id ();
$ t -> string ( ' label ' );
$ t -> bool ( ' status ' );
} );
}
};
在 PHP 文件中,始终首先包含namespace
语句。 use
语句是可选的,仅需要作为闭包函数参数的类型提示的快捷方式。您的类还必须从“Base”任务类扩展或实现“Iface”任务接口。
除了匿名类之外,您还可以使用命名类来执行迁移任务:
<?php
namespace Aimeos Upscheme Task ;
use Aimeos Upscheme Schema Table ;
class TestTable extends Base
{
public function up ()
{
$ this -> db ()-> table ( ' test ' , function ( Table $ t ) {
$ t -> id ();
$ t -> string ( ' label ' );
$ t -> bool ( ' status ' );
} );
}
}
存储类的文件必须与类本身具有相同的名称(区分大小写)和.php
后缀,例如:
class TestTable -> TestTable.php
对于如何命名迁移任务文件没有严格的约定。您可以根据它们的功能(例如“CreateTestTable.php”)、它们的操作内容(例如“TestTable.php”)来命名它们,甚至可以使用时间戳(例如“20201231_Test.php”)。
如果任务不包含依赖项,则会根据文件名按字母顺序排序并执行,排序为:
20201231_Test.php
CreateTestTable.php
TestTable.php
要指定对其他迁移任务的依赖关系,请使用after()
和before()
方法。您的任务在after()
返回的任务之后和before()
返回的任务之前执行:
return new class ( $ this ) extends Base {
public function after () : array
{
return [ ' CreateRefTable ' ];
}
public function before () : array
{
return [ ' InsertTestData ' ];
}
}
任务名称是不带.php
后缀的任务的文件名。如果示例迁移存储在文件TestTable.php
中,则执行顺序为:
CreateRefTable.php -> TestTable.php -> InsertTestData.php
要在迁移任务中输出消息,请使用info()
方法:
$ this -> info ( ' some message ' );
$ this -> info ( ' more verbose message ' , ' vv ' );
$ this -> info ( ' very verbose debug message ' , ' vvv ' );
第二个参数是详细级别,none 或v
是标准消息, vv
是仅在需要更多详细程度时才显示的消息,而vvv
用于调试消息。还有第三个参数用于缩进消息:
$ this -> info ( ' some message ' );
$ this -> info ( ' second level message ' , ' v ' , 1 );
$ this -> info ( ' third level message ' , ' v ' , 2 );
这将显示:
some message
second level message
third level message
前提是Up
类的verbose()
方法之前已经被调用过:
Aimeos Upscheme Up:: use ( $ config , ' ... ' )-> verbose ()-> up ();
在up()
方法中,您可以使用db()
方法访问数据库模式。如果您将多个数据库配置传递给Up::use()
,您可以通过配置键访问不同的模式:
// $config = [ 'db' => [ ... ] , 'temp' => [ ... ] ] ;
// Aimeos UpschemeUp::use( $config , '...' )->up() ;
$ this -> db ();
$ this -> db ( ' db ' );
$ this -> db ( ' temp ' );
如果您未传递配置键或不存在的配置键,则返回第一个配置(在本例中为“db”)。通过使用数据库模式对象的可用方法,您可以添加、更新或删除表、列、索引和其他数据库对象。此外,您还可以使用insert()
、 select()
、 update()
、 delete()
和stmt()
来操作表的记录。
每次迁移任务完成后,任务中进行的架构更新将自动应用到数据库。如果因为要插入数据而需要立即保留更改,请自行调用$this->db()->up()
。 up()
方法也可在任何表、序列和列对象中使用,因此您可以在任何地方调用up()
。
如果您需要两个不同的数据库连接,因为您想同时执行 SELECT 和 INSERT/UPDATE/DELETE 语句,请将 TRUE 作为第二个参数传递给db()
以获取包含新连接的数据库模式:
$ db1 = $ this -> db ();
$ db2 = $ this -> db ( ' db ' , true );
foreach ( $ db1 -> select ( ' users ' , [ ' status ' => false ] ) as $ row ) {
$ db2 -> insert ( ' oldusers ' , $ row );
}
$ db2 -> delete ( ' users ' , [ ' status ' => false ] );
在返回具有新连接的架构之前,所做的所有架构更改都会应用到数据库。为了避免数据库连接堆积直到数据库服务器拒绝新连接,请始终对db( '<name>', true )
创建的新连接调用close()
:
$ db2 -> close ();
您可以使用以下命令自动生成迁移文件,而不是手动为数据库对象编写迁移:
$ config = [
' db ' => [
' driver ' => ' pdo_mysql ' ,
' host ' => ' 127.0.0.1 ' ,
' dbname ' => ' <database> ' ,
' user ' => ' <dbuser> ' ,
' password ' => ' <secret> '
]
];
Aimeos Upscheme Up:: use ( $ config , ' migrations ' )-> create ();
这将为传递的目录中的每个序列、表和视图生成一个文件(本例中为./migrations/
)。如果您有多个数据库并希望一次为所有数据库创建迁移,请将连接键从配置传递到create()
:
$ config = [
' db ' => [
' driver ' => ' pdo_mysql ' ,
// ...
],
' order ' => [
' driver ' => ' pdo_oci ' ,
// ...
]
];
Aimeos Upscheme Up:: use ( $ config , ' migrations ' )-> create ( [ ' db ' , ' order ' ] );
您可以通过调用$this->db()
来获取任务中的数据库架构对象,如架构部分中所述。它使您可以完全访问数据库模式,包括所有表、序列和其他模式对象:
$ table = $ this -> db ()-> table ( ' users ' );
$ seq = $ this -> db ()-> sequence ( ' seq_users ' );
如果表或序列不存在,则会创建它。否则,返回现有的表或序列对象。在这两种情况下,您都可以随后修改对象并向表中添加新列等。
您可以使用$this->db()
返回的数据库模式测试表、列、索引、外键和序列:
$ db = $ this -> db ();
if ( $ db -> hasTable ( ' users ' ) ) {
// The "users" table exists
}
if ( $ db -> hasColumn ( ' users ' , ' name ' ) ) {
// The "name" column in the "users" table exists
}
if ( $ db -> hasIndex ( ' users ' , ' idx_name ' ) ) {
// The "idx_name" index in the "users" table exists
}
if ( $ db -> hasForeign ( ' users_address ' , ' fk_users_id ' ) ) {
// The foreign key "fk_users_id" in the " users_address " table exists
}
if ( $ db -> hasSequence ( ' seq_users ' ) ) {
// The "seq_users" sequence exists
}
if ( $ db -> hasView ( ' testview ' ) ) {
// The "testview" view exists
}
$this->db()
返回的数据库对象提供了使用renameTable()
、 renameColumn()
和renameIndex()
重命名表、列和索引的可能性:
$ db = $ this -> db ();
// Renames the table "users" to "accounts"
$ db -> renameTable ( ' users ' , ' account ' );
// Renames the column "label" to "name" in the "users" table
$ db -> renameColumn ( ' users ' , ' label ' , ' name ' );
// Renames the column "idx_label" to "idx_name" in the "users" table
$ db -> renameIndex ( ' users ' , ' idx_label ' , ' idx_name ' );
$this->db()
返回的数据库对象还具有删除表、列、索引、外键和序列的方法:
$ db = $ this -> db ();
// Drops the foreign key " fk_users_id " from the " users_address " table
$ db -> dropForeign ( ' users_address ' , ' fk_users_id ' );
// Drops the " idx_name " index from the " users " table
$ db -> dropIndex ( ' users ' , ' idx_name ' );
// Drops the " name " column from the " users " table
$ db -> dropColumn ( ' users ' , ' name ' );
// Drops the "seq_users" sequence
$ db -> dropSequence ( ' seq_users ' );
// Drops the "users" table
$ db -> dropTable ( ' users ' );
// Drops the "testview" view
$ db -> dropView ( ' testview ' );
如果表、列、索引、外键或序列不存在,则会被静默忽略。对于需要知道它们是否存在的情况,请使用之前的hasTable()
、 hasColumn()
、 hasIndex()
、 hasForeign()
和hasSeqence()
方法,如“检查是否存在”部分中所述。
insert()
、 select()
、 update()
和delete()
方法是在任何表中添加、检索、修改和删除行的简单方法:
$ this -> db ()-> transaction ( function ( $ db ) {
$ db2 = $ this -> db ( ' db ' , true );
foreach ( $ db2 -> select ( ' users ' , [ ' status ' => false ] ) as $ row )
{
$ db -> insert ( ' newusers ' , [ ' userid ' => $ row [ ' id ' ], ' status ' => true ] );
$ db -> update ( ' users ' , [ ' refid ' => $ db -> lastId ()], [ ' id ' => $ row [ ' id ' ]] );
}
$ db -> delete ( ' newusers ' , [ ' status ' => false ] );
$ db2 -> close ();
} );
如果同时使用select()
和insert()
、 update()
或delete()
,则必须创建第二个数据库连接,因为select()
语句将在您向数据库服务器发送新命令时返回行。这只适用于单独的连接,不适用于同一连接。
要将所有删除/插入/更新操作包装到事务中,必须使用数据库对象的transaction()
方法:
$ this -> db ()-> transaction ( function ( $ db ) {
// $db- > insert ( ... )
// $db- > update ( ... )
// $db- > delete ( ... )
} );
这可确保所有写入操作均以原子方式执行,或者在发生错误时不执行任何写入操作。 transaction()
方法确保在匿名函数将控制权返回给该方法后自动提交或回滚事务。
如果您的匿名函数中需要其他参数,您可以将它们移交给函数的use
列表:
$ userid = 123 ;
$ this -> db ()-> transaction ( function ( $ db ) use ( $ userid ) {
$ db -> insert ( ' newusers ' , [ ' userid ' => userid, ' status ' => true ] );
} );
您只能将条件的简单键/值对传递给通过 AND 组合的方法。如果您需要更复杂的查询,请使用stmt()
代替:
$ db = $ this -> db ();
$ result = $ db -> stmt ()-> select ( ' id ' , ' name ' )
-> from ( ' users ' )
-> where ( ' status != ? ' )
-> setParameter ( 0 , false )
-> executeQuery ();
$ db -> stmt ()-> delete ( ' users ' )
-> where ( ' status != ? ' )
-> setParameter ( 0 , false )
-> executeStatement ();
$ db -> stmt ()-> update ( ' users ' )
-> set ( ' status ' , ' ? ' )
-> where ( ' status != ? ' )
-> setParameters ( [ true , false ] )
-> executeStatement ();
stmt()
方法返回一个DoctrineDBALQueryQueryBuilder
对象,它使您能够构建更高级的语句。请查看 Doctrine Query Builder 文档以获取更多详细信息。
如果您想直接在 SQL 语句中使用值(出于安全原因,请尽可能使用准备好的语句!),您必须使用q()
方法引用这些值:
$ db = $ this -> db ();
$ result = $ db -> stmt ()-> select ( ' * ' )-> from ( ' products ' )
-> where ( ' status = ' . $ db -> q ( $ _GET [ ' status ' ] ) )-> executeQuery ();
同样,如果您的模式包含保留关键字(例如作为列名),您也必须使用qi()
方法引用它们:
$ db = $ this -> db ();
$ result = $ db -> stmt ()-> select ( $ db -> qi ( ' key ' ) )-> from ( ' products ' )-> executeQuery ();
Doctrine 仅支持 SQL 语句的公共子集,而不支持数据库供应商已实现的所有可能性。为了消除该限制,Upscheme 提供了exec()
、 for()
和query()
方法来执行 Doctrine DBAL 不支持的自定义 SQL 语句。
要执行自定义 SQL 查询,请使用query()
方法,该方法返回您可以迭代的结果集:
$ sql = ' SELECT id, label, status FROM product WHERE label LIKE ? ' ;
$ result = $ this -> db ()-> query ( $ sql , [ ' test% ' ] );
foreach ( $ result -> iterateAssociative () as $ row ) {
// ...
}
对于所有其他 SQL 语句,请使用exec()
方法,该方法返回受影响的行数:
$ sql = ' UPDATE product SET status=? WHERE status=? ' ;
$ num = $ this -> db ()-> exec ( $ sql , [ 1 , 0 ] );
使用for()
方法,您还可以根据数据库平台执行语句:
$ this -> db ()-> for ( ' mysql ' , ' CREATE FULLTEXT INDEX idx_text ON product (text) ' );
指定数据库平台对于创建特殊类型的索引非常有用,其中数据库实现之间的语法不同。
调用自定义方法或将未知方法调用传递给 Doctrine 模式对象
public function __call( string $ method , array $ args )
$method
方法名称$args
方法参数示例:
您可以注册有权访问 Upscheme DB 对象的类属性的自定义方法:
Aimeos Upscheme Schema DB :: macro ( ' hasFkIndexes ' , function ( $ val ) {
return $ this -> to -> hasExplicitForeignKeyIndexes ();
} );
$ db -> hasFkIndexes ();
// returns true / false
可用的类属性有:
$this->from
:代表当前数据库的原始 Doctrine 数据库模式
$this->to
:包含迄今为止所做更改的 Doctrine 数据库模式
$this->conn
: Doctrine 数据库连接
$this->up
: Upscheme 对象
此外,您可以直接调用任何 Doctrine 模式方法,例如:
$ db -> hasExplicitForeignKeyIndexes ();
关闭数据库连接
public function close() : void
仅对使用$this->db( '...', true )
创建的数据库模式对象调用close()
。否则,您将关闭主连接,并且 DBAL 必须重新连接到服务器,这会降低性能!
示例:
$ db = $ this -> db ( ' temp ' , true );
$ db -> dropTable ( ' test ' );
$ db -> close ();
从给定表中删除记录
public function delete( string $ table , array $ conditions = [] ) : self
$table
表名$conditions
列名的键/值对和要比较的值警告:条件值已转义,但表名称和条件列名称未转义!仅使用固定字符串作为表名和条件列名,但不能使用外部输入!
示例:
$ db -> delete ( ' test ' , [ ' status ' => false , ' type ' => ' old ' ] );
$ db -> delete ( ' test ' );
第二个参数中传入的几个条件由“AND”组合而成。如果您需要更复杂的语句,请使用stmt()
方法。
删除由其名称给出的列(如果存在)
public function dropColumn( string $ table , $ name ) : self
$table
该列所属的表的名称$name
一个或多个列的名称示例:
$ db -> dropColumn ( ' test ' , ' oldcol ' );
$ db -> dropColumn ( ' test ' , [ ' oldcol ' , ' oldcol2 ' ] );
如果该列或其中一列不存在,它将被默默地忽略。
删除由其名称给出的外键约束(如果存在)
public function dropForeign( string $ table , $ name ) : self
$table
外键约束所属表的名称$name
一个或多个外键约束的名称示例:
$ db -> dropForeign ( ' test ' , ' fk_old ' );
$ db -> dropForeign ( ' test ' , [ ' fk_old ' , ' fk_old2 ' ] );
如果外键约束或约束之一不存在,它将被默默地忽略。
删除由其名称给出的索引(如果存在)
public function dropIndex( string $ table , $ name ) : self
$table
索引所属表的名称$name
一个或多个索引的名称示例:
$ db -> dropIndex ( ' test ' , ' idx_old ' );
$ db -> dropIndex ( ' test ' , [ ' idx_old ' , ' idx_old2 ' ] );
如果索引或索引之一不存在,它将被默默地忽略。
删除由其名称给出的序列(如果存在)
public function dropSequence( $ name ) : self
$name
一个或多个序列的名称示例:
$ db -> dropSequence ( ' seq_old ' );
$ db -> dropSequence ( [ ' seq_old ' , ' seq_old2 ' ] );
如果序列或序列之一不存在,它将被默默地忽略。
删除由其名称给出的表(如果存在)
public function dropTable( $ name ) : self
$name
一个或多个表的名称示例:
$ db -> dropTable ( ' test ' );
$ db -> dropTable ( [ ' test ' , ' test2 ' ] );
如果该表或其中一张表不存在,它将被默默地忽略。
删除由其名称给出的视图(如果存在)
public function dropView( $ name ) : self
$name
视图的名称示例:
$ db -> dropView ( ' test ' );
$ db -> dropView ( [ ' test ' , ' test2 ' ] );
如果视图或视图之一不存在,它将被默默地忽略。
执行自定义 SQL 语句
public function exec( string $ sql , array $ params = [], array $ types = [] ) : int
$sql
自定义SQL语句$params
位置参数列表或占位符和参数的关联列表$types
位置或关联占位符参数的 DBAL 数据类型列表数据库更改不会立即应用,因此请务必在执行自定义语句之前调用 up() 以确保您要使用的表之前已创建!
示例:
$ sql = ' UPDATE product SET status=? WHERE status=? ' ;
$ num = $ this -> db ()-> exec ( $ sql , [ 1 , 0 ] );
如果数据库属于给定类型,则执行自定义 SQL 语句
public function for( $ type , $ sql ) : self
$type
语句应执行的数据库类型$sql
自定义 SQL 语句或语句可用的数据库平台类型有:
数据库更改不会立即应用,因此请务必在执行自定义语句之前调用up()
以确保您要使用的表之前已创建!
示例:
$ db -> for ( ' mysql ' , ' CREATE INDEX idx_test_label ON test (label(16)) ' );
$ db -> for ( [ ' mysql ' , ' sqlite ' ], [
' DROP INDEX unq_test_status ' ,
' UPDATE test SET status = 0 WHERE status IS NULL ' ,
] );
检查一个或多个列是否存在
public function hasColumn( string $ table , $ name ) : bool
$table
该列所属的表的名称$name
一个或多个列的名称示例:
$ db -> hasColumn ( ' test ' , ' testcol ' );
$ db -> hasColumn ( ' test ' , [ ' testcol ' , ' testcol2 ' ] );
检查外键约束是否存在
public function hasForeign( string $ table , $ name ) : bool
$table
外键约束所属表的名称$name
一个或多个外键约束的名称示例:
$ db -> hasForeign ( ' test ' , ' fk_testcol ' );
$ db -> hasForeign ( ' test ' , [ ' fk_testcol ' , ' fk_testcol2 ' ] );
检查索引是否存在
public function hasIndex( string $ table , $ name ) : bool
$table
索引所属表的名称$name
一个或多个索引的名称示例:
$ db -> hasIndex ( ' test ' , ' idx_test_col ' );
$ db -> hasIndex ( ' test ' , [ ' idx_test_col ' , ' idx_test_col2 ' ] );
检查序列是否存在
public function hasSequence( $ name ) : bool
$name
一个或多个序列的名称示例:
$ db -> hasSequence ( ' seq_test ' );
$ db -> hasSequence ( [ ' seq_test ' , ' seq_test2 ' ] );
检查表是否存在
public function hasTable( $ name ) : bool
$name
一个或多个表的名称示例:
$ db -> hasTable ( ' test ' );
$ db -> hasTable ( [ ' test ' , ' test2 ' ] );
检查视图是否存在
public function hasView( $ name ) : bool
$name
视图的名称示例:
$ db -> hasView ( ' test ' );
$ db -> hasView ( [ ' test ' , ' test2 ' ] );
将记录插入给定表中
public function insert( string $ table , array $ data ) : self
$table
表名$data
要插入的列名称/值的键/值对示例:
$ db -> insert ( ' test ' , [ ' label ' => ' myvalue ' , ' status ' => true ] );
返回任意数据库表中最后插入行的 ID
public function lastId() : string
注意:这不适用于 Oracle 平台,因为 Doctrine DBAL 目前不支持 Oracle IDENTITY 列。
示例:
$ db -> lastId ();
返回数据库的名称
public function name() : string
示例:
$ db -> name ();
引用一个值
public function q( $ value , $ type = Doctrine DBAL ParameterType:: STRING ) : string
$value
在未准备的 SQL 查询中使用的值$type
DBAL 参数类型示例:
$ result = $ db -> stmt ()-> select ( ' * ' )-> from ( ' products ' )
-> where ( ' status = ' . $ db -> q ( $ _GET [ ' status ' ] ) )-> executeQuery ();
引用数据库标识符
public function qi( string $ identifier ) : string
$identifier
标识符,如表名或列名示例:
$ result = $ db -> stmt ()-> select ( $ db -> qi ( ' key ' ) )-> from ( ' products ' )-> executeQuery ();
执行自定义 SQL 查询
public function query( string $ sql , array $ params = [], array $ types = [] ) : Doctrine DBAL Result
$sql
自定义SQL语句$params
位置参数列表或占位符和参数的关联列表$types
位置或关联占位符参数的 DBAL 数据类型列表示例:
$ result = $ db -> query ( ' SELECT id, label, status FROM product WHERE label LIKE ? ' , [ ' test% ' ] );
foreach ( $ result -> iterateAssociative () as $ row ) {
// ...
}
提示:检查用于检索数据的 DBAL 方法以获取更多信息。
重命名列或列列表
public function renameColumn( string $ table , $ from , string $ to = null ) : self
$table
表名$from
列名或旧/新列名数组$to
如果第一个参数是数组,则忽略新列名如果该列尚不存在,该方法将成功,但不会发生任何事情。不需要调用up()
。
局限性
示例:
// single column
$ db -> renameColumn ( ' testtable ' , ' test_col ' , ' test_column ' );
// rename several columns at once
$ db -> renameColumn ( ' testtable ' , [ ' tcol ' => ' testcol ' , ' tcol2 ' => ' testcol2 ' ] );
重命名列或列列表
public function renameIndex( string $ table , $ from , string $ to = null ) : self
$table
表名$from
索引名称或旧/新索引名称数组$to
如果第一个参数是数组,则忽略新索引名称如果索引尚不存在,该方法将成功,但什么也不会发生。不需要调用up()
。
示例:
// single index
$ db -> renameIndex ( ' testtable ' , ' idxcol ' , ' idx_column ' );
// rename several indexes at once
$ db -> renameIndex ( ' testtable ' , [ ' idxcol ' => ' idx_column ' , ' idxcol2 ' => ' idx_column2 ' ] );
重命名表或表列表
public function renameTable( $ from , string $ to = null ) : self
$from
表名或旧/新表名数组$to
如果第一个参数是数组,则忽略新表名称如果该表尚不存在,该方法将成功,但不会发生任何事情。不需要调用up()
。
示例:
// single table
$ db -> renameTable ( ' testtable ' , ' newtable ' );
// rename several tables at once
$ db -> renameTable ( [ ' testtable ' => ' newtable ' , ' oldtable ' => ' testtable2 ' ] );
重新加载当前数据库的实际 Doctrine 模式
public function reset() : self
示例:
$ db -> reset ();
返回给定表中的记录
public function select( string $ table , array $ conditions = null ) : array
$table
表名$conditions
列名的键/值对和要比较的值示例:
$ db -> select ( ' test ' , [ ' status ' => false , ' type ' => ' old ' ] );
$ db -> select ( ' test ' );
第二个参数中传入的几个条件由“AND”组合而成。如果您需要更复杂的语句,请改用stmt()
方法。
返回给定名称的序列对象
public function sequence( string $ name , Closure $ fcn = null ) : Sequence
$name
序列的名称$fcn
使用 ($sequence) 参数创建或更新序列定义的匿名函数如果序列尚不存在,则会创建它。要保留数据库中的更改,您必须调用up()
。
示例:
$ sequence = $ db -> sequence ( ' seq_test ' );
$ sequence = $ db -> sequence ( ' seq_test ' , function ( $ seq ) {
$ seq -> start ( 1000 )-> step ( 2 )-> cache ( 100 );
} )-> up ();
返回新 SQL 语句的查询生成器
public function stmt() : Doctrine DBAL Query QueryBuilder
示例:
$ db -> stmt ()-> delete ( $ db -> qi ( ' test ' ) )
-> where ( $ db -> qi ( ' stat ' ) . ' = ? ' )-> setParameter ( 0 , false )
-> executeStatement ();
$ db -> stmt ()-> update ( $ db -> qi ( ' test ' ) )
-> where ( $ db -> qi ( ' stat ' ) . '' , ' ? ' )-> setParameter ( 0 , true )
-> executeStatement ();
$ result = $ db -> stmt ()-> select ( $ db -> qi ( ' id ' ), $ db -> qi ( ' code ' ) )
-> from ( $ db -> qi ( ' test ' ) )
-> where ( $ db -> qi ( ' stat ' ) . ' = 1 ' )
-> executeQuery ();
while ( $ row = $ result -> fetchAssociative () ) {
$ id = $ row [ ' id ' ];
}
**警告:** 您必须使用$db->qi()
方法自己引用所有表和列名称!
有关可用 Doctrine QueryBuilder 方法的更多详细信息,请查看 Doctrine 文档。
返回给定名称的表对象
public function table( string $ name , Closure $ fcn = null ) : Table
$name
表的名称$fcn
使用 ($table) 参数创建或更新表定义的匿名函数如果该表尚不存在,则会创建该表。要保留数据库中的更改,您必须调用up()
。
示例:
$ table = $ db -> table ( ' test ' );
$ table = $ db -> table ( ' test ' , function ( $ t ) {
$ t -> id ();
$ t -> string ( ' label ' );
$ t -> bool ( ' status ' );
} )-> up ();
在事务中执行给定的闭包
public function transaction( Closure $ fcn ) : self
示例:
$ this -> db ()-> transaction ( function ( $ db ) {
// $db- > insert ( ... )
// $db- > update ( ... )
// $db- > delete ( ... )
} );
从数据库中以数组形式返回对象
public function toArray() : array
示例:
$ this -> db ()-> toArray ();
返回的数组结构为:
[
' sequence ' => [
' testseq ' => [
' name ' => ' testseq ' ,
' cache ' => null ,
' start ' => 1000 ,
' step ' => 1
]
],
' table ' => [
' testtable ' => [
' name ' => ' testtable ' ,
' opt ' => [
' engine ' => ' InnoDB ' ,
' collation ' => ' utf8mb4_unicode_ci ' ,
' charset ' => ' utf8mb4 ' ,
' autoincrement ' => 1 ,
' comment ' => ''
],
' col ' => [
' id ' => [
' name ' => ' id ' ,
' type ' => ' integer ' ,
' length ' => null ,
' precision ' => null ,
' scale ' => 0 ,
' null ' => false ,
' seq ' => 1
' default ' => null,
' fixed ' => false ,
' unsigned ' => false ,
' comment ' => '' ,
' opt ' => []
],
' parentid ' => [
' name ' => ' parentid ' ,
' type ' => ' bigint ' ,
' length ' => null ,
' precision ' => null ,
' scale ' => 0 ,
' null ' => false ,
' seq ' => false ,
' default ' => null ,
' fixed ' => false ,
' unsigned ' => false ,
' comment ' => '' ,
' opt ' => []
],
' label ' => [
' name ' => ' label ' ,
' type ' => ' string ' ,
' length ' => 255 ,
' precision ' => null ,
' scale ' => 0 ,
' null ' => false ,
' seq ' => false ,
' default ' => null ,
' fixed ' => false ,
' unsigned ' => false ,
' comment ' => '' ,
' opt ' => [
' charset ' => ' utf8mb4 ' ,
' collation ' => ' utf8mb4_unicode_ci '
]
]
],
' index ' => [
' PRIMARY ' => [
' columns ' => [
0 => ' id '
],
' name ' => ' PRIMARY ' ,
' flags ' => [],
' options ' => [
' lengths ' => [
0 => null
]
],
' unique ' => 1 ,
' primary ' => 1
],
],
' foreign ' => [
' FK_6C73FFCA343B91AE ' => [
' localcol ' => [
0 => ' parentid '
],
' fktable ' => ' test ' ,
' fkcol ' => [
0 => ' id '
],
' name ' => ' FK_6C73FFCA343B91AE ' ,
' onDelete ' => ' CASCADE ' ,
' onUpdate ' => ' CASCADE '
]
]
]
],
' view ' => [
' testview ' => [
' name ' => ' testview ' ,
' sql ' => ' select `testtable`.`id` AS `id`,`testtable`.`label` AS `label` from `testtable` '
]
]
]
返回数据库的类型
public function type() : string
可能的值为:
示例:
$ type = $ db -> type ();
将更改应用到数据库架构
public function up() : self
示例:
$ db -> up ();
更新给定表中的记录
public function update( string $ table , array $ data , array $ conditions = [] ) : self
$table
表名$data
要更新的列名称/值的键/值对$conditions
列名和要比较的值的键/值对示例:
$ db -> update ( ' test ' , [ ' status ' => true ] );
$ db -> update ( ' test ' , [ ' status ' => true ], [ ' status ' => false , ' type ' => ' new ' ] );
第二个参数中传入的几个条件由“AND”组合而成。如果您需要更复杂的语句,请使用stmt()
方法。
如果视图尚不存在,则创建具有给定名称的视图
public function view( string $ name , string $ sql , $ for = null ) : self
$name
视图的名称$sql
用于填充视图的 SELECT 语句$for
此 SQL 应该用于的数据库类型(“mysql”、“mariadb”、“postgresql”、“sqlite”、“sqlserver”、“oracle”、“db2”)如果视图尚不存在,则会创建它。否则,什么也不会发生。
示例:
$ db -> view ( ' testview ' , ' SELECT * FROM testtable ' );
$ db -> view ( ' testview ' , ' SELECT id, label, status FROM testtable WHERE status = 1 ' );
$ db -> view ( ' testview ' , ' SELECT * FROM `testtable` WHERE `status` = 1 ' , ' mysql ' );
通过在迁移任务中调用table()
获得的表方案对象使您可以完全访问该表,并且可以添加、更改或删除列、索引和外键,例如:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
$ table -> id ();
$ table -> string ( ' label ' );
$ table -> col ( ' status ' , ' tinyint ' )-> default ( 0 );
} );
除了可以添加任意类型的列的col()
方法之外,所有数据库服务器实现中还有一些类型的快捷方法:
立柱类型 | 描述 |
---|---|
比吉德 | 具有序列/自动增量和分配的主键的 BIGINT 列 |
大整数 | BIGINT 列,范围从 −9223372036854775808 到 9223372036854775807 |
二进制 | VARBINARY 列最多 255 个字节 |
斑点 | 最大 2GB 的 BLOB 列 |
布尔值 | BOOLEAN/BIT/NUMBER 列,“布尔值”的别名 |
布尔值 | BOOLEAN/BIT/NUMBER 列分别表示 TRUE/FALSE。 0/1 值 |
字符 | 具有固定字符数的 CHAR 列 |
日期 | ISO 日期格式 ("YYYY-MM-DD) 的 DATE 列,不含时间和时区 |
日期时间 | ISO 日期/时间格式的 DATETIME 列 ("YYYY-MM-DD HH:mm:ss" ) |
表日期时间 | 采用 ISO 日期/时间格式但具有不同时区格式的 DATETIMETZ 列 |
小数 | 用于具有定点精度的数值数据的 DECIMAL 列(PHP 中的字符串) |
漂浮 | FLOAT 列,用于具有 8 字节浮点精度的数值数据 |
指导 | 36字节全局唯一标识符 |
ID | 具有序列/自动增量和分配的主键的 INTEGER 列 |
整数 | INTEGER 列,“整数”的别名 |
整数 | 整数列,范围从 -2147483648 到 2147483647 |
json | UTF-8 编码 JSON 数据的 JSON 列 |
小整数 | 整数列,范围从 -32768 到 32767 |
细绳 | VARCHAR 列最多包含 255 个字符 |
文本 | TEXT/CLOB 列最多包含 2GB 字符 |
时间 | 24 小时制“HH:MM”格式的时间列,例如“05:30”或“22:15” |
uuid | 36 字节的全局唯一标识符,别名“guid” |
MySQL(或 MariaDB 等)支持一些选项来定义表的各个方面。引擎选项将指定用于表的存储引擎:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
$ table -> opt ( ' engine ' , ' InnoDB ' );
} );
作为快捷方式,还可以将该选项设置为属性:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
$ table -> engine = ' InnoDB ' ;
} );
要创建临时表,请使用:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
$ table -> temporary = true ;
} );
还可以为字符串和文本列设置默认字符集和排序规则:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
$ table -> charset = ' utf8mb4 ' ;
$ table -> collation = ' utf8mb4_unicode_ci ' ;
} );
注意: PostgreSQL 和 SQL Server 也支持排序规则,但它们的值不同。因此,不可能对所有服务器类型使用相同的值。要避免该问题,请使用列opt()
方法并将数据库服务器类型作为第三个参数传递:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
$ table -> opt ( ' charset ' , ' utf8mb4 ' , ' mysql ' );
$ table -> opt ( ' collation ' , ' utf8mb4_unicode_ci ' , ' mysql ' );
} );
现在,默认字符集和排序规则将仅为 MySQL 数据库服务器(或 MariaDB 和类似的分支)设置。
如果您需要知道表选项的当前值:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
// return the used table engine ( only MySQL , MariaDB , etc . )
$ engine = $ table -> engine ;
// returns TRUE if it ' s a temporary table
$ isTemp = $ table -> temporary ;
// return the current charset
$ charset = $ table -> charset ;
// return the current collation
$ collation = $ table -> collation ;
} );
要检查表是否已存在,请使用hasTable()
方法:
if ( $ this -> db ()-> hasTable ( ' users ' ) ) {
// The "users" table exists
}
您也可以同时检查多个表:
if ( $ this -> db ()-> hasTable ( [ ' users ' , ' addresses ' ] ) ) {
// The "users" and "addresses" tables exist
}
仅当所有表都存在时, hasTable()
方法才会返回 TRUE。
除了创建和访问表之外,模式对象中的table()
方法也可用于更新表模式。它接受表名和将接收表模式对象的闭包。
让我们首先创建一个名为test的表,其中包含三列:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
$ table -> id ();
$ table -> string ( ' label ' );
$ table -> col ( ' status ' , ' tinyint ' )-> default ( 0 );
} );
现在,我们想要通过添加代码列并更改现有状态列的默认值来更新另一个迁移中的表:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
$ table -> string ( ' code ' );
$ table -> col ( ' status ' , ' tinyint ' )-> default ( 1 );
} );
table()
方法返回后,更改将保存在数据库中,因此之后无需自己调用up()
。有关可用的色谱柱类型和选项,请参阅色谱柱部分。
$this->db()
返回的数据库对象可以在使用renameTable()
方法时重命名表:
// Renames the table "users" to "accounts"
$ this -> db ()-> renameTable ( ' users ' , ' account ' );
如果您传递一个关联数组,其中旧名称和新名称作为键/值对,也可以一次重命名多个表:
// Renames the table "users" to "accounts" and "blog" to "posts"
$ this -> db ()-> renameTable ( [ ' users ' => ' account ' , ' blog ' => ' posts ' ] );
仅当表存在时才重命名。如果表不再存在,则不会报告错误:
$ this -> db ()-> renameTable ( ' notexist ' , ' newtable ' );
在这种情况下,方法调用将成功,但什么也不会发生。
要删除表,您应该使用数据库模式中的dropTable()
方法:
$ this -> db ()-> dropTable ( ' users ' );
您还可以通过将列表作为数组传递来一次删除多个表:
$ this -> db ()-> dropTable ( [ ' users ' , ' addresses ' ] );
仅当表存在时才会将其删除。如果表不再存在,则不会报告错误:
$ this -> db ()-> dropTable ( ' notexist ' );
在这种情况下,方法调用将成功,但什么也不会发生。
调用自定义方法或将未知方法调用传递给 Doctrine 表对象
public function __call( string $ method , array $ args )
$method
方法名称$args
方法参数示例:
您可以注册有权访问 Upscheme Table 对象的类属性的自定义方法:
Aimeos Upscheme Schema Table:: macro ( ' addConstraint ' , function ( array $ columns ) {
return $ this -> to -> addUniqueConstraint ( $ columns );
} );
$ table -> addConstraint ( [ ' col1 ' , ' col2 ' ] );
可用的类属性有:
$this->table
: Doctrine 表模式
$this->up
: Upscheme 对象
此外,您可以直接调用任何 Doctrine 表方法,例如:
$ table -> addUniqueConstraint ( [ ' col1 ' , ' col2 ' ] );
返回给定表选项的值
public function __get( string $ name )
$name
表选项名称可用表选项的列表是:
示例:
$ engine = $ table -> engine ;
// same as
$ engine = $ table -> opt ( ' engine ' );
设置给定表选项的新值
public function __set( string $ name , $ value )
$name
表选项名称可用表选项的列表是:
示例:
$ table -> engine = ' InnoDB ' ;
// same as
$ table -> opt ( ' engine ' , ' InnoDB ' );
创建一个“bigint”类型的新 ID 列或返回现有的 ID 列
public function bigid( string $ name = null ) : Column
$name
ID 列的名称该列获得一个序列(自动增量)和自动分配的主键。如果该列尚不存在,则会创建它。
示例:
$ table -> bigid ();
$ table -> bigid ( ' uid ' );
创建“bigint”类型的新列或返回现有列
public function bigint( string $ name ) : Column
$name
列的名称如果该列尚不存在,则会创建它。
示例:
$ table -> bigint ( ' testcol ' );
创建“二进制”类型的新列或返回现有列
public function binary( string $ name , int $ length = 255 ) : Column
$name
列的名称$length
列的长度(以字节为单位)如果该列尚不存在,则会创建它。
示例:
$ table -> binary ( ' testcol ' );
$ table -> binary ( ' testcol ' , 32 );
创建“blob”类型的新列或返回现有列
public function blob( string $ name , int $ length = 0x7fff ) : Column
$name
列的名称$length
列的长度(以字节为单位)“blob”列的最大长度为 2GB。如果该列尚不存在,则会创建它。
示例:
$ table -> blob ( ' testcol ' );
$ table -> blob ( ' testcol ' , 0x7fffffff );
创建“布尔”类型的新列或返回现有列
public function bool( string $ name ) : Column
$name
列的名称该方法是 boolean() 的别名。如果该列尚不存在,则会创建它。
示例:
$ table -> bool ( ' testcol ' );
创建“布尔”类型的新列或返回现有列
public function boolean( string $ name ) : Column
$name
列的名称如果该列尚不存在,则会创建它。
示例:
$ table -> boolean ( ' testcol ' );
创建具有固定类型的“char”类型的新列或返回现有列
public function char( string $ name , int $ length ) : Column
$name
列的名称$length
列的长度(以字符为单位)如果该列尚不存在,则会创建它。
示例:
$ table -> char ( ' testcol ' , 3 );
创建新列或返回现有列
public function col( string $ name , string $ type = null ) : Column
$name
列的名称$type
列的类型如果该列尚不存在,则会创建它。
示例:
$ table -> col ( ' testcol ' );
$ table -> col ( ' testcol ' , ' tinyint ' );
创建“日期”类型的新列或返回现有列
public function date( string $ name ) : Column
$name
列的名称如果该列尚不存在,则会创建它。
示例:
$ table -> date ( ' testcol ' );
创建“datetime”类型的新列或返回现有列
public function datetime( string $ name ) : Column
$name
列的名称如果列还不存在,将创建它。
示例:
$ table -> datetime ( ' testcol ' );
创建一个类型“ DateTimetz”的新列或返回现有的列
public function datetimetz( string $ name ) : Column
$name
列的名称如果列还不存在,将创建它。
示例:
$ table -> datetimetz ( ' testcol ' );
创建一个类型“小数”的新列或返回现有的列
public function decimal( string $ name , int $ digits , int $ decimals = 2 ) : Column
$name
列的名称$digits
总数的总数(包括小数)$decimals
小数点数字之后的数字数如果列还不存在,将创建它。
示例:
$ table -> decimal ( ' testcol ' , 10 ); // 10 digits incl . 2 decimals
$ table -> decimal ( ' testcol ' , 10 , 4 ); // 10 digits incl . 4 decimals
如果存在,则将其名称给出
public function dropColumn( $ name ) : self
$name
列或列的名称如果列或一列不存在,则将被默默地忽略。在调用迁移任务完成或调用up()
之前,不会应用更改。
示例:
$ table -> dropColumn ( ' testcol ' );
$ table -> dropColumn ( [ ' testcol ' , ' testcol2 ' ] );
如果存在
public function dropIndex( $ name ) : self
$name
索引或索引的名称名称如果不存在索引或索引之一,则将被默默地忽略。在调用迁移任务完成或调用up()
之前,不会应用更改。
示例:
$ table -> dropIndex ( ' idx_test_col ' );
$ table -> dropIndex ( [ ' idx_test_col ' , ' idx_test_col2 ' ] );
如果存在,则删除其名称给出的外键约束
public function dropForeign( $ name ) : self
$name
名称如果不存在外键约束或其中一个约束,则将被静默地忽略。在调用迁移任务完成或调用up()
之前,不会应用更改。
示例:
$ table -> dropForeign ( ' fk_test_col ' );
$ table -> dropForeign ( [ ' fk_test_col ' , ' fk_test_col2 ' ] );
如果存在,则将主要密钥丢弃
public function dropPrimary() : self
如果主要键不存在,它将被默默地忽略。在调用迁移任务完成或调用up()
之前,不会应用更改。
示例:
$ table -> dropPrimary ();
创建一个“ float”类型的新列或返回现有的列
public function float( string $ name ) : Column
$name
列的名称如果列还不存在,将创建它。
示例:
$ table -> float ( ' testcol ' );
创建一个新的外键或返回现有的键
public function foreign( $ localcolumn , string $ foreigntable , $ foreigncolumn = ' id ' , string $ name = null ) : Foreign
$localcolumn
名称本地列或列的名称$foreigntable
名称$foreigncolumn
名称引用列或列$name
for Autogenerated Name的外键约束的名称和外键索引或null外国密钥名称的长度应不超过30个字符,以最大程度地兼容。
示例:
$ table -> foreign ( ' parentid ' , ' test ' );
$ table -> foreign ( ' parentid ' , ' test ' , ' uid ' );
$ table -> foreign ( ' parentid ' , ' test ' , ' id ' , ' fk_test_pid ' );
$ table -> foreign ( [ ' parentid ' , ' siteid ' ], ' test ' , [ ' uid ' , ' siteid ' ] );
创建“ GUID”类型的新列或返回现有的列
public function guid( string $ name ) : Column
$name
列的名称如果列还不存在,将创建它。
示例:
$ table -> guid ( ' testcol ' );
检查列是否存在
public function hasColumn( $ name ) : bool
$name
列或列的名称示例:
$ table -> hasColumn ( ' testcol ' );
$ table -> hasColumn ( [ ' testcol ' , ' testcol2 ' ] );
检查索引是否存在
public function hasIndex( $ name ) : bool
$name
索引或索引的名称名称示例:
$ table -> hasIndex ( ' idx_test_col ' );
$ table -> hasIndex ( [ ' idx_test_col ' , ' idx_test_col2 ' ] );
检查外键约束是否存在
public function hasForeign( $ name ) : bool
$name
名称示例:
$ table -> hasForeign ( ' fk_test_col ' );
$ table -> hasForeign ( [ ' fk_test_col ' , ' fk_test_col2 ' ] );
创建一个新的ID列“整数”或返回现有的ID列
public function id( string $ name = null ) : Column
$name
id列的名称名称该列获得一个序列(自动启动)和一个主键自动分配。如果列还不存在,将创建它。
示例:
$ table -> id ();
$ table -> id ( ' uid ' );
创建新索引或替换现有的索引
public function index( $ columns , string $ name = null ) : self
$columns
列列或列的名称产卵索引$name
索引名称或自动化名称为null索引名称的长度应不超过30个字符,以最大程度地兼容。
示例:
$ table -> index ( ' testcol ' );
$ table -> index ( [ ' testcol ' , ' testcol2 ' ] );
$ table ->index( ' testcol ' , 'idx_test_testcol );
创建一个新的“整数”类型或返回现有的列
public function int( string $ name ) : Column
$name
列的名称此方法是Integer()的别名。如果列还不存在,将创建它。
示例:
$ table -> int ( ' testcol ' );
创建一个新的“整数”类型或返回现有的列
public function integer( string $ name ) : Column
$name
列的名称如果列还不存在,将创建它。
示例:
$ table -> integer ( ' testcol ' );
创建一个新的“ JSON”类型或返回现有的列
public function json( string $ name ) : Column
$name
列的名称如果列还不存在,将创建它。
示例:
$ table -> json ( ' testcol ' );
返回表的名称
public function name() : string
示例:
$ tablename = $ table -> name ();
设置自定义架构选项或返回当前值
public function opt( string $ name , $ value = null )
$name
与表相关的自定义模式选项$value
定制架构选项的值可用的自定义模式选项是:
示例:
$ charset = $ table -> opt ( ' charset ' );
$ table -> opt ( ' charset ' , ' utf8 ' )-> opt ( ' collation ' , ' utf8_bin ' );
// Magic methods :
$ charset = $ table -> charset ;
$ table -> charset = ' binary ' ;
创建新的主要索引或替换现有的索引
public function primary( $ columns , string $ name = null ) : self
$columns
列列或列的名称产卵索引$name
索引名称或自动化名称为null索引名称的长度应不超过30个字符,以最大程度地兼容。
示例:
$ table -> primary ( ' testcol ' );
$ table -> primary ( [ ' testcol ' , ' testcol2 ' ] );
$ table -> primary ( ' testcol ' , ' pk_test_testcol ' );
重命名列或列列表
public function renameColumn( $ from , string $ to = null ) : self
$from
列名或旧/新列名的数组$to
null $ to New列名如果第一个参数为数组示例:
// single column
$ table -> renameColumn ( ' test_col ' , ' test_column ' );
// rename several columns at once
$ table -> renameColumn ( [ ' tcol ' => ' testcol ' , ' tcol2 ' => ' testcol2 ' ] );
重命名索引或索引列表
public function renameIndex( $ from , string $ to = null ) : self
$from
索引名称或旧/新索引名称的数组(如果新索引名称为null,则将生成)$to
新索引名称或用于自动化名称的null(如果第一个参数为数组,则忽略)索引名称的长度应不超过30个字符,以最大程度地兼容。
示例:
// generate a new name automatically
$ table -> renameIndex ( ' test_col_index ' );
// custom name
$ table -> renameIndex ( ' test_col_index ' , ' idx_test_col ' );
// rename several indexes at once
$ table -> renameIndex ( [ ' test_col_index ' => null , ' test_index ' => ' idx_test_col ' ] );
创建一个新的“ SmallInt”类型或返回现有的列
public function smallint( string $ name ) : Column
$name
列的名称如果列还不存在,将创建它。
示例:
$ table -> smallint ( ' testcol ' );
创建一个新的空间索引或替换现有的索引
public function spatial( $ columns , string $ name = null ) : self
$columns
列列或列的名称产卵索引$name
索引名称或自动化名称为null索引名称的长度应不超过30个字符,以最大程度地兼容。
示例:
$ table -> spatial ( ' testcol ' );
$ table -> spatial ( [ ' testcol ' , ' testcol2 ' ] );
$ table -> spatial ( ' testcol ' , ' idx_test_testcol ' );
创建一个类型“字符串”的新列或返回现有的列
public function string( string $ name , int $ length = 255 ) : Column
$name
列的名称$length
长度的字符长度这种类型应最多可用于255个字符。有关更多字符,请使用“文本”类型。如果列还不存在,将创建它。
示例:
$ table -> string ( ' testcol ' );
$ table -> string ( ' testcol ' , 32 );
创建一个类型“文本”或返回现有的列的新列
public function text( string $ name , int $ length = 0xffff ) : Column
$name
列的名称$length
长度的字符长度“文本”列的最大长度为2GB。如果列还不存在,将创建它。
示例:
$ table -> text ( ' testcol ' );
$ table -> text ( ' testcol ' , 0x7fffffff );
创建一个新的类型“时间”列或返回现有的列
public function time( string $ name ) : Column
$name
列的名称如果列还不存在,将创建它。使用Oracle数据库时,该数据类型不可用。
示例:
$ table -> time ( ' testcol ' );
创建一个新的唯一索引或替换现有的索引
public function unique( $ columns , string $ name = null ) : self
$columns
列列或列的名称产卵索引$name
索引名称或自动化名称为null索引名称的长度应不超过30个字符,以最大程度地兼容。
示例:
$ table -> unique ( ' testcol ' );
$ table -> unique ( [ ' testcol ' , ' testcol2 ' ] );
$ table -> unique ( ' testcol ' , ' unq_test_testcol ' );
创建“ GUID”类型的新列或返回现有的列
public function uuid( string $ name ) : Column
$name
列的名称此方法是GUID()的别名。如果列还不存在,将创建它。
示例:
$ table -> uuid ( ' testcol ' );
将更改应用于数据库模式
public function up() : self
示例:
$ table -> up ();
您通过在迁移任务中调用col()
获得的列架模式对象可让您访问所有列属性。也有所有数据库支持的列类型的快捷方式。每个列可以通过一种或多种修饰符方法更改,您还可以将索引添加到单列,例如:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
$ table -> id ()-> unsigned ( true );
$ table -> string ( ' label ' )-> index ();
$ table -> col ( ' status ' , ' tinyint ' )-> default ( 0 );
} );
该示例将添加以下列:
所有数据库服务器实现中可用的列类型都有一些快捷方式:
立柱类型 | 描述 |
---|---|
bigid | 带有序列/自动启动和主键分配的Bigint列 |
大整数 | bigint柱,范围为-9223372036854775808到9223372036854775807 |
二进制 | 最多255个字节的Varbinary列 |
斑点 | 斑点列,最多2GB |
布尔值 | 布尔/位/数字柱,别名为“布尔” |
布尔值 | 布尔语/位/数字colum for true/false resp。 0/1值 |
字符 | 字符数量固定的字符列 |
日期 | ISO日期格式(“ yyyy-mm-dd)的日期列无时间和时区 |
日期时间 | ISO日期/时间格式的DateTime列(“ Yyyy-MM-DD HH:MM:SS”) |
TablesDateTimetz | ISO的DateTimetz列以ISO日期/时间格式,但具有不同的时区格式 |
小数 | 数字数据的十进制列具有定点精度(php中的字符串) |
漂浮 | 带有8字节浮点精度的数字数据的浮列 |
指导 | 具有36个字节的全球唯一标识符 |
ID | 带有序列/自动插入和主键分配的整数列 |
整数 | 整数Colum,“整数”的别名 |
整数 | 整数柱,范围为-2147483648到2147483647 |
json | UTF-8编码JSON数据的JSON列 |
小整数 | 整数柱,范围为-32768至32767 |
细绳 | 最多255个字符的Varchar列 |
文本 | 最多2GB字符的文本/clob列 |
时间 | 时间列24小时“ HH:mm” Fromat,例如“ 05:30”或“ 22:15” |
uuid | 具有36个字节的全球唯一标识符,“ GUID”的别名 |
要添加数据库特定的列类型,请使用col()
方法,例如:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
$ table -> col ( ' status ' , ' tinyint ' );
} );
也可以通过调用一个或多个列修改器方法来更改列定义:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
$ table -> int ( ' number ' )-> null ( true )-> unsigned ( true );
} );
可用的列修改器方法是:
列修饰符 | 描述 |
---|---|
自动插入(true) | 将整数列设置为自动插入( seq() 的别名) |
charset('utf8') | 列(mySQL)使用的字符集 |
整理(“二进制”) | 列整理(mysql/postgresql/sqlite/sqlserver,但不兼容) |
评论(“评论”) | 将注释添加到列(mysql/postgresql/oracle/sqlserver) |
默认(1) | 如果未指定值(默认值: NULL ),则列的默认值 |
固定(true) | 如果字符串或二进制列应具有固定的长度 |
索引('idx_col') | 在列中添加索引,索引名称是可选的 |
长度(32) | 最大。字符串和二进制列的长度 |
null(true) | 允许将 NULL 值插入到列中 |
精度(12) | 最大。数字数量存储在十进制和浮子柱中。小数位 |
主('pk_col') | 将主键添加到列,主键名是可选的 |
比例尺(2) | 十进制和浮柱中使用的十进制数字的确切数量 |
seq(true) | 如果未指定值 |
空间('idx_col') | 在列中添加空间(GEO)索引,索引名称是可选的 |
唯一('unq_col') | 在列中添加唯一索引,索引名称是可选的 |
未签名(true) | 仅允许无符号整数值(MySQL) |
要设置列的自定义模式选项,请使用opt()
方法,例如:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
$ table -> string ( ' code ' )-> opt ( ' collation ' , ' utf8mb4 ' );
} );
甚至可以通过将数据库类型作为第三参数传递给特定数据库实现的特定数据库实现的列修饰符:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
$ table -> string ( ' code ' )-> opt ( ' collation ' , ' utf8mb4 ' , ' mysql ' );
} );
要检查是否已经存在列,请使用hasColumn()
方法:
if ( $ this -> db ()-> hasColumn ( ' users ' , ' name ' ) ) {
// The "name" column in the "users" table exists
}
您也可以一次检查几列。在这种情况下,只有在所有列存在时, hasColumn()
方法才会返回true:
if ( $ this -> db ()-> hasColumn ( ' users ' , [ ' name ' , ' status ' ] ) ) {
// The "name" and "status" columns in the "users" table exists
}
如果您已经有一个表对象,则可以使用hasColumn()
:
if ( $ table -> hasColumn ( ' name ' ) ) {
// The "name" column in the table exists
}
if ( $ table -> hasColumn ( [ ' name ' , ' status ' ] ) ) {
// The "name" and "status" columns in the table exists
}
除列外,您还可以检查是否设置了列修饰符以及它们具有哪些值:
if ( $ table -> string ( ' code ' )-> null () ) {
// The "code" columns is nullable
}
使用以下方法可以检索当前的列修饰符值:
列修饰符 | 描述 |
---|---|
自动插入() | 如果列自动插入( seq() 的别名),则为true |
字符集() | 二手字符集(mysql) |
colation() | 使用的分组(mysql/postgresql/sqlite/sqlserver,但不兼容) |
评论() | 评论与列(MySQL/Postgresql/Oracle/SQLServer)关联 |
默认() | 列的默认值 |
固定的() | 如果字符串或二进制列的长度固定 |
长度() | 字符串或二进制列的最大长度 |
无效的() | 如果允许零值 |
精确() | 包含十进制和浮动柱中的最大数字数量。小数位 |
规模() | 十进制和浮柱中使用的十进制数字的确切数量 |
seq() | 如果列自动插入 |
unsigned() | 如果只允许使用未签名的整数值(mySQL),则为正确 |
要检查非标准列修饰符,请使用没有第二个参数的opt()
方法。然后,它将返回列修改器的当前值:
if ( $ table -> string ( ' code ' )-> opt ( ' charset ' ) === ' utf8 ' ) {
// The "code" columns uses UTF - 8 charset ( MySQL only)
}
可以更改大多数列修饰符,例如字符串列的长度:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
$ table -> string ( ' code ' )-> length ( 64 );
} );
某些方法还提供了其他参数,可以直接设置最常使用的修饰符:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
$ table -> string ( ' code ' , 64 );
} );
如果您需要立即更改列修饰符,因为您要之后要迁移行,请使用up()
方法持续更改:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
$ table -> string ( ' code ' , 64 )-> null ( true )-> up ();
// modify rows from "test" table
} );
通过使用适当类型或col()
方法的新方法更改列类型:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
$ table -> text ( ' code ' );
// or
$ table -> col ( ' code ' , ' text ' );
} );
请注意,并非所有列类型都可以更改为另一种类型,或者至少没有数据丢失。您可以将整数列更改为毫无问题的bigint列,但反过来会失败。如果要将varchar列(字符串)更改为整数列,也会发生同样的情况。
要重命名列,请使用DB模式的renameColumn()
方法:
// single column
$ this -> db ()-> renameColumn ( ' testtable ' , ' label ' , ' name ' );
// multiple columns
$ this -> db ()-> renameColumn ( ' testtable ' , [ ' label ' => ' name ' , ' stat ' => ' status ' ] );
如果已经可用表对象,则可以使用其renameColumn()
方法重命名一个或多列:
$ this -> db ()-> table ( ' testtable ' , function ( $ table ) {
// single column
$ table -> renameColumn ( ' label ' , ' name ' );
// multiple columns
$ table -> renameColumn ( [ ' label ' => ' name ' , ' stat ' => ' status ' ] );
} );
在所有情况下,仅在存在时删除列。如果表中不存在一个或多个列,则不会报告错误。
要删除列,请使用DB架构对象的dropColumn()
方法:
$ this -> db ()-> dropColumn ( ' users ' , ' name ' );
如果要将所有要丢弃为数组的列的名称的名称,则可以立即删除几列:
$ this -> db ()-> dropColumn ( ' users ' , [ ' name ' , ' status ' ] );
如果您已经有一个表对象,则也可以使用dropColumn()
:
// single column
$ table -> dropColumn ( ' name ' );
// multiple columns
$ table -> dropColumn ( [ ' name ' , ' status ' ] );
在所有情况下,仅在存在时删除列。如果表中不存在一个或多个列,则不会报告错误。
调用自定义方法或将未知方法调用到学说列对象
public function __call( string $ method , array $ args )
$method
名称该方法的名称$args
方法参数示例:
您可以注册可以访问Upscheme列对象的类属性的自定义方法:
Aimeos Upscheme Schema Column:: macro ( ' platform ' , function ( array $ options ) {
return $ this -> to -> setPlatformOptions ( $ options );
} );
$ column -> platform ( [ ' option ' => ' value ' ] );
可用的类属性是:
$this->db
:upscheme db对象
$this->table
:学说表模式
$this->column
:学说列模式
此外,您可以直接调用任何学说列方法,例如:
$ column -> setPlatformOptions ( [ ' option ' => ' value ' ] );
返回给定列选项的值
public function __get( string $ name )
$name
列选项名称可用列选项的列表是:
示例:
$ charset = $ column -> charset ;
// same as
$ charset = $ column -> opt ( ' charset ' );
设置给定列选项的新值
public function __set( string $ name , $ value )
$name
列选项名称$value
Common选项值可用列选项的列表是:
示例:
$ column -> charset = ' utf8 ' ;
// same as
$ column -> opt ( ' charset ' , ' utf8 ' );
将列设置为自动插入或返回当前值
public function autoincrement( bool $ value = null )
$value
新自动启动标志或null以返回当前值此方法是seq()
方法的别名。
示例:
$ value = $ column -> autoincrement ();
$ column -> autoincrement ( true );
设置列Charset或返回当前值
public function charset( string $ value = null )
$value
新列charset或null以返回当前值示例:
$ comment = $ column -> charset ();
$ column -> charset ( ' utf8 ' );
设置列整理或返回当前值
public function collation( string $ value = null )
$value
新列整理或null以返回当前值示例:
$ comment = $ column -> collation ();
$ column -> collation ( ' binary ' );
设置列注释或返回当前值
public function comment( string $ value = null )
$value
新列注释或null以返回当前值示例:
$ comment = $ column -> comment ();
$ column -> comment ( ' column comment ' );
设置列默认值或返回当前值
public function default( $ value = null )
$value
新列默认值或null以返回当前值示例:
$ value = $ column -> default ();
$ column -> default ( 0 );
设置列固定标志或返回当前值
public function fixed( bool $ value = null )
$value
新列固定标志或null以返回当前值示例:
$ value = $ column -> fixed ();
$ column -> fixed ( true );
为列创建常规索引
public function index( string $ name = null ) : self
$name
null index或null的名称自动生成示例:
$ column -> index ();
$ column -> index ( ' idx_col ' );
设置列长度或返回当前值
public function length( int $ value = null )
$value
新列长度或null以返回当前值示例:
$ value = $ column -> length ();
$ column -> length ( 32 );
返回列的名称
public function name() : string
示例:
$ name = $ column -> name ();
设置列null标志或返回当前值
public function null( bool $ value = null )
$value
新列null标志或null以返回当前值示例:
$ value = $ column -> null ();
$ column -> null ( true );
设置列选项值或返回当前值
public function opt( string $ option , $ value = null , $ for = null )
$option
列选项名称名称$value
新列选项值或null以返回当前值$for
数据库类型的null $此选项应用于(“ mysql”,“ mariadb”,“ postgresql”,“ sqlite”,“ sqlite”,“ sqlserver”,“ oracle”,“ oracle”,“ db2”))示例:
$ value = $ column -> opt ( ' length ' );
$ column -> opt ( ' length ' , 64 );
设置列精度或返回当前值
public function precision( int $ value = null )
$value
新列精度值或null返回当前值示例:
$ value = $ column -> precision ();
$ column -> precision ( 10 );
为列创建主要索引
public function primary( string $ name = null ) : self
$name
null index或null的名称自动生成示例:
$ column -> primary ();
$ column -> primary ( ' pk_col ' );
设置列秤或返回当前值
public function scale( int $ value = null )
$value
新的列刻度值或null以返回当前值示例:
$ value = $ column -> scale ();
$ column -> scale ( 3 );
将列设置为自动插入或返回当前值
public function seq( bool $ value = null )
$value
新自动启动标志或null以返回当前值示例:
$ value = $ column -> seq ();
$ column -> seq ( true );
为列创建空间索引
public function spatial( string $ name = null ) : self
$name
null index或null的名称自动生成示例:
$ column -> spatial ();
$ column -> spatial ( ' idx_col ' );
设置列类型或返回当前值
public function type( string $ value = null )
$value
新列类型或null以返回当前值示例:
$ value = $ column -> type ();
$ column -> type ( ' tinyint ' );
为列创建唯一索引
public function unique( string $ name = null ) : self
$name
null index或null的名称自动生成示例:
$ column -> unique ();
$ column -> unique ( ' unq_col ' );
设置列无符号标志或返回当前值
public function unsigned( bool $ value = null )
$value
新列无符号标志或null以返回当前值示例:
$ value = $ column -> unsigned ();
$ column -> unsigned ( true );
将更改应用于数据库模式
public function up() : self
示例:
$ column -> up ();
Upscheme提供了对外国密钥约束的支持,该限制可以在两个表之间实施数据的完整性。例如,如果users_address
表的parentid
列引用users
表的id
列,则users
表中的users_address
表中没有行中没有匹配行。调用foreign()
方法将创建这样的约束:
$ this -> db ()-> table ( ' users ' , function ( $ table ) {
$ table -> id ();
} );
$ this -> db ()-> table ( ' users_address ' , function ( $ table ) {
$ table -> foreign ( ' parentid ' , ' users ' );
} );
注意:列( parentid
)将并且必须具有与引用列( id
)相同的数据类型和列修饰符。 foreign()
方法可确保并将创建一个与外键约束相同名称的新索引。
如果users
表中的ID列以不同的命名,请将其名称作为第三参数传递给foreign()
方法:
$ this -> db ()-> table ( ' users_address ' , function ( $ table ) {
$ table -> foreign ( ' parentid ' , ' users ' , ' uid ' );
} );
建议将外键约束的名称作为第四参数,以便以后更改或删除约束:
$ this -> db ()-> table ( ' users_address ' , function ( $ table ) {
$ table -> foreign ( ' parentid ' , ' users ' , ' id ' , ' fk_test_pid ' );
} );
如果需要多个列来获取外国密钥所需的唯一值,请将列名作为数组传递:
$ this -> db ()-> table ( ' users_address ' , function ( $ table ) {
$ table -> foreign ( [ ' parentid ' , ' siteid ' ], ' users_address ' , [ ' id ' , ' siteid ' ] );
} );
如果外国表中的引用列已删除,则外键约束可以执行不同的操作。标准操作是限制删除行或更新引用ID值。要改变行为,请使用onDelete()
和onUpdate()
方法:
$ this -> db ()-> table ( ' users_address ' , function ( $ table ) {
$ table -> foreign ( ' parentid ' , ' users ' )-> onDelete ( ' SET NULL ' )-> onUpdate ( ' RESTRICT ' );
} );
如果要将两个值设置为相同的值,则有一个快捷方式:
$ this -> db ()-> table ( ' users_address ' , function ( $ table ) {
$ table -> foreign ( ' parentid ' , ' users ' )-> do ( ' SET NULL ' );
} );
两种方法的可能值是:
删除或更新行时的默认操作是级联的,因此外键列的值被更新为与外部表中相同的值。
要检查是否已经存在外键,请使用hasForeign()
方法:
if ( $ this -> db ()-> hasForeign ( ' users_address ' , ' fk_usrad_parentid ' ) ) {
// The "fk_usrad_parentid" foreign key in the " users_address " table exists
}
也可能一次检查几个外键约束。然后,只有在第一个参数传递的表中所有约束中存在所有约束时, hasForeign()
方法才会返回true:
if ( $ this -> db ()-> hasForeign ( ' users_address ' , [ ' fk_usrad_parentid ' , ' fk_usrad_siteid ' ] ) ) {
// The "fk_usrad_parentid" and "fk_usrad_siteid" foreign keys exist in the "users_address" table
}
如果可用的表对象,则可以使用表的hasForeign()
方法:
$ this -> db ()-> table ( ' users_address ' , function ( $ table ) {
$ table -> hasForeign ( ' fk_usrad_parentid ' ) ) {
// The "fk_usrad_parentid" foreign key in the " users_address " table exists
}
} );
$ this -> db ()-> table ( ' users_address ' , function ( $ table ) {
$ table -> hasForeign ( [ ' fk_usrad_parentid ' , ' fk_usrad_siteid ' ] ) ) {
// The "fk_usrad_parentid" and "fk_usrad_siteid" foreign keys exist in the "users_address" table
}
} );
如果您需要现有约束的当前值:
$ this -> db ()-> table ( ' users_address ' , function ( $ table ) {
$ fk = $ table -> foreign ( ' parentid ' , ' users ' );
// returns the name of the constraint
$ name = $ fk -> name ()
// returns the action when deleting rows
$ action = $ fk -> onDelete ;
// returns the action when updating the foreign ID
$ action = $ fk -> onUpdate ;
} );
要从表中删除外键约束,请使用dropForeign()
方法,然后将表和外键名的名称传递为参数:
$ this -> db ()-> dropForeign ( ' users_address ' , ' fk_usrad_parentid ' );
您也可以通过几个外键名来立即将其放下:
$ this -> db ()-> dropForeign ( ' users_address ' , [ ' fk_usrad_parentid ' , ' fk_usrad_siteid ' ] );
在传递给table()
方法的匿名函数中,您还可以使用dropForeign()
方法:
$ this -> db ()-> table ( ' users_address ' , function ( $ table ) {
$ table -> dropForeign ( ' fk_usrad_parentid ' );
} );
$ this -> db ()-> table ( ' users_address ' , function ( $ table ) {
$ table -> dropForeign ( [ ' fk_usrad_parentid ' , ' fk_usrad_siteid ' ] );
} );
调用自定义方法
public function __call( string $ method , array $ args )
$method
名称该方法的名称$args
方法参数示例:
您可以注册可以访问Upscheme异物的类属性的自定义方法:
Aimeos Upscheme Schema Foreign:: macro ( ' default ' , function () {
$ this -> opts = [ ' onDelete ' => ' SET NULL ' , ' onUpdate ' => ' SET NULL ' ];
} );
$ foreign -> default ();
可用的类属性是:
$this->dbaltable
:学说表模式
$this->table
:upscheme表对象
$this->localcol
:本地列名称或名称
$this->fktable
:外桌名称
$this->fkcol
:外国列名称或名称
$this->name
:外钥匙名称
$this->opts
:外键选项的关联列表(主要是“ ondelete”和“ onupdate”)
返回给定外国密钥选项的价值
public function __get( string $ name )
$name
外键选项名称可用外键选项的列表是:
这两个选项的可能值是:
示例:
$ value = $ foreign -> onDelete ;
// same as
$ value = $ foreign -> opt ( ' onDelete ' );
为给定的外键选项设置新值
public function __set( string $ name , $ value )
$name
外键选项名称可用外键选项的列表是:
这两个选项的可能值是:
示例:
$ foreign -> onDelete = ' SET NULL ' ;
// same as
$ foreign -> onDelete ( ' SET NULL ' );
$ foreign -> opt ( ' onDelete ' , ' SET NULL ' );
为给定的外键选项设置新值
public function do( string $ action ) : self
$action
执行动作可能采取的行动有:
示例:
$ foreign -> do ( ' RESTRICT ' );
public function name()
示例:
$ fkname = $ foreign -> name ();
public function onDelete( string $ value = null )
@param字符串| null $value
执行的操作或null以返回当前值
@return self |字符串相同的对象用于设置值,当前值无参数
可用操作是:
示例:
$ value = $ foreign -> onDelete ();
$ foreign -> onDelete ( ' SET NULL ' );
// same as
$ foreign -> onDelete = ' SET NULL ' ;
// same as
$ foreign -> opt ( ' onDelete ' , ' SET NULL ' );
$ foreign -> onDelete ( ' SET NULL ' )-> onUpdate ( ' SET NULL ' );
public function onUpdate( string $ value = null )
@param字符串| null $value
执行的操作或null以返回当前值
@return self |字符串相同的对象用于设置值,当前值无参数
可用操作是:
示例:
$ value = $ foreign -> onUpdate ();
$ foreign -> onUpdate ( ' SET NULL ' );
// same as
$ foreign -> onUpdate = ' SET NULL ' ;
// same as
$ foreign -> opt ( ' onUpdate ' , ' SET NULL ' );
$ foreign -> onUpdate ( ' SET NULL ' )-> onDelete ( ' SET NULL ' );
public function up() : self
示例:
$ foreign -> up ();
一些数据库实现提供了序列,而不是自动灌溉/身份列,即Oracle和PostgreSQL。序列是在插入新行时会依次增加数字的函数。要创建一个名为seq_test的新序列,请使用sequence()
方法:
$ this -> db ()-> sequence ( ' seq_test ' );
要使用不同的启动值和步骤宽度大于1
,请调用start()
和step()
方法:
$ this -> db ()-> sequence ( ' seq_test ' , function ( $ seq ) {
$ seq -> start ( 1000 )-> step ( 2 );
} );
要检查序列是否已经存在,请使用hasSequence()
方法:
if ( $ this -> db ()-> hasSequence ( ' seq_test ' ) ) {
// The "seq_test" sequence exists
}
也可能一次检查几个序列。然后,只有在所有hasSequence()
存在时才返回true true:
if ( $ this -> db ()-> hasSequence ( [ ' seq_id ' , ' seq_test ' ] ) ) {
// The "seq_id" and "seq_test" sequences exist
}
如果您需要知道表选项的当前值:
$ this -> db ()-> sequence ( ' seq_test ' , function ( $ seq ) {
// returns how many generated numbers are cached
$ cache = $ seq -> cache ;
// returns the number the sequence has started from
$ start = $ seq -> start ;
// returns the step width for newly generated numbers
$ step = $ seq -> step ;
} );
要删除序列,请使用dropSequence()
方法,然后将序列的名称传递为参数:
$ this -> db ()-> dropSequence ( ' seq_id ' );
您还可以传递几个序列名称以立即将它们放置:
$ this -> db ()-> dropSequence ( [ ' seq_id ' , ' seq_test ' ] );
调用自定义方法或将未知方法调用到学说表对象
public function __call( string $ method , array $ args )
$method
名称该方法的名称$args
方法参数示例:
您可以注册可以访问Upscheme序列对象的类属性的自定义方法:
Aimeos Upscheme Schema Sequence:: macro ( ' default ' , function () {
$ this -> start ( 1 )-> step ( 2 );
} );
$ sequence -> default ();
可用的类属性是:
$this->db
:upscheme db对象
$this->sequence
:学说序列模式
返回给定序列选项的值
public function __get( string $ name )
$name
序列选项名称示例:
$ value = $ sequence -> getInitialValue ();
// same as
$ value = $ sequence -> start ();
为给定序列选项设置新值
public function __set( string $ name , $ value )
$name
序列选项名称示例:
$ value = $ sequence -> setInitialValue ( 1000 );
// same as
$ value = $ sequence -> start ( 1000 );
设置序列的缓存大小或返回当前值
public function cache( int $ value = null )
$value
新数字的序列ID由客户端或null缓存以返回当前值示例:
$ value = $ sequence -> cache ();
$ sequence -> cache ( 100 );
返回序列的名称
public function name()
$ name = $ sequence -> name ();
设置序列的新启动值或返回当前值
public function start( int $ value = null )
$value
序列的新启动值或null以返回当前值 $ value = $ sequence -> start ();
$ sequence -> start ( 1000 );
设置新序列值的步长或返回当前值
public function step( int $ value = null )
$value
新步骤大小该序列被逐渐增加或减少或缩小以返回当前值 $ value = $ sequence -> step ();
$ sequence -> step ( 2 );
将更改应用于数据库模式
public function up() : self
$ sequence -> up ();
索引加快数据库查询以及查询需求可以正确使用的时间从几分钟下降到毫秒。有几种索引类型:
所有索引都可以由一个或多个列组成,但是如果索引用于查询,则列的顺序会产生很大的影响。
所有索引都绑定到包含索引覆盖的列的表。通过单列创建索引的最简单方法是使用列对象的index()
方法:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
$ table -> string ( ' label ' )-> index ();
} );
index()
方法的第二个参数允许您为索引设置自定义名称:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
$ table -> string ( ' label ' )-> index ( ' idx_test_label ' );
} );
注意:对于不同数据库类型之间的最大兼容性,索引名称的长度应为30个字符或更小。
主要,独特和空间索引也可以:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
// primary key
$ table -> int ( ' id ' )-> primary ();
$ table -> int ( ' id ' )-> primary ( ' pk_test_id ' ); // ignored by MySQL , MariaDB , etc .
// unique key
$ table -> string ( ' code ' )-> unique ();
$ table -> string ( ' code ' )-> unique ( ' unq_test_code ' );
// spatial index
$ table -> col ( ' location ' , ' point ' )-> spatial ();
$ table -> col ( ' location ' , ' point ' )-> spatial ( ' idx_test_location ' );
} );
对于多列索引,表对象中有primary()
, unique()
和index()
方法:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
// primary composite index
$ table -> primary ( [ ' siteid ' , ' code ' ] );
// unique composite index
$ table -> unique ( [ ' parentid ' , ' type ' ] );
// regular composite index
$ table -> index ( [ ' label ' , ' status ' ] );
} );
空间索引不能跨越多个列,但是使用表对象的spatial()
方法也可以创建它们:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
$ table -> spatial ( ' location ' );
} );
要检查索引是否已经存在,请使用hasIndex()
方法:
if ( $ this -> db ()-> hasIndex ( ' users ' , ' idx_users_name ' ) ) {
// The "idx_users_name" index in the "users" table exists
}
您也可以一次检查几个索引。在这种情况下,只有在所有索引存在时才返回hasIndex()
:
if ( $ this -> db ()-> hasIndex ( ' users ' , [ ' idx_users_name ' , ' idx_users_status ' ] ) ) {
// The "idx_users_name" and "idx_users_status" indexes in the "users" table exists
}
如果您已经有一个表对象,则可以使用hasIndex()
:
if ( $ table -> hasIndex ( ' idx_users_name ' ) ) {
// The "idx_users_name" index in the table exists
}
if ( $ table -> hasIndex ( [ ' idx_users_name ' , ' idx_users_status ' ] ) ) {
// The "idx_users_name" and "idx_users_status" indexes in the table exists
}
使用DB架构的renameIndex()
方法直接重命名索引:
// single index
$ this -> db ()-> renameIndex ( ' testtable ' , ' idx_test_label ' , ' idx_test_name ' );
// multiple indexes
$ this -> db ()-> renameIndex ( ' testtable ' , [ ' idx_test_label ' => ' idx_test_name ' , ' idx_text_stat ' => ' idx_test_status ' ] );
如果已经可用表对象,则可以使用其renameIndex()
方法重命名一个或多个索引:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
// single index
$ table -> renameIndex ( ' idx_test_label ' , ' idx_test_name ' );
// multiple indexes
$ table -> renameIndex ( [ ' idx_test_label ' => ' idx_test_name ' , ' idx_text_stat ' => ' idx_test_status ' ] );
} );
在所有情况下,索引仅在存在时都会重命名。如果表中不存在一个或多个索引,则不会报告错误。
要删除索引,请使用DB架构对象的dropIndex()
方法:
$ this -> db ()-> dropIndex ( ' users ' , ' idx_test_name ' );
如果您传递了要删除为数组的所有索引的名称,则可以一次删除几个索引:
$ this -> db ()-> dropIndex ( ' users ' , [ ' idx_test_name ' , ' idx_test_status ' ] );
如果您已经有一个表对象,则也可以使用dropIndex()
:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
// single index
$ table -> dropIndex ( ' idx_test_name ' );
// multiple indexes
$ table -> dropIndex ( [ ' idx_test_name ' , ' idx_test_status ' ] );
} );
在所有情况下,索引仅在存在时被删除。 No error is reported if one or more indexes doesn't exist in the table.
It's not necessary to pass a custom index name when creating new indexes. Then, the index name is generated automatically but their name will consist of a hash that is hard to read. Also, you don't know which columns the indexes span from the index name.
Upscheme allows you to add your own naming function for indexes which is used if not index name is passed to the methods for creating indexes. Before running the migrations, register your nameing function using the macro()
method in the table objects:
use Aimeos Upscheme Schema Table ;
Table:: marco ( ' nameIndex ' , function ( string $ table , array $ columns , string $ type ) {
return $ type . ' _ ' . $ table . ' _ ' . join ( ' _ ' , $ columns );
} );
Aimeos Upscheme Up:: use ( $ config , ' ./migrations/ ' )-> up ()
For a table "testtable", a column "label" and the type "idx", this will return idx_testtable_label instead of a hash.
Available index types are:
Note: For compatibility to all supported database types, the maximum length of the index names must be not longer than 30 characters!
You can add new methods to all Upscheme objects using the macro()
method. Each custom method has access to the class properties and methods of the class it's registered for including the Doctrine DBAL objects.
To register a method named test()
in the DB schema object with two parameters $arg1
and $arg2
which has access to the same class properties as the DB __call()
method use:
Aimeos Upscheme Schema DB :: marco ( ' test ' , function ( $ arg1 , $ arg2 ) {
// $ this - >conn : Doctrine connection
// $this - >from : Doctrine start schema
// $this - >to : Doctrine current schema
// $ this - >up : Upscheme object
// return $this or a value
} );
$ db -> test ( ' key ' , ' value ' );
Registering a method test()
in the Table schema object with one parameter $arg1
which has access to the same class properties as the Table __call()
method use:
Aimeos Upscheme Schema Table:: marco ( ' test ' , function ( $ arg1 ) {
// $this - >db : Upscheme DB object
// $this - >table : Doctrine Table object
// return $this or a value
} );
$ table -> test ( ' something ' );
Same for a method test()
in the Column schema object with an optional parameter $value
which has access to the same class properties as the Column __call()
method use:
Aimeos Upscheme Schema Column:: marco ( ' test ' , function ( $ value = null ) {
// $this - >db : Upscheme DB object
// $this - >table : Upscheme Table object
// $this - >column : Doctrine Column object
// return $this or a value
} );
$ column -> test ();
To extend the Foreign object for foreign key constraints with a test()
method with no parameter having access to the same class properties as the Foreign __call()
method use:
Aimeos Upscheme Schema Foreign:: marco ( ' test ' , function () {
// $this - >table : Upscheme Table object
// $this - >dbaltable : Doctrine Table object
// $this - >localcol : Array of local column names
// $this - >fktable : Foreign table name
// $ this - >fkcol : Foreign table column names
// $this - >name : Foreign key name
// $ this - >opts : Array of foreign key options ( "onDelete" and "onUpdate")
// return $this or a value
} );
$ foreign -> test ();
Finally, extending the Sequence object with a test()
method having no parameters and access to the same class properties as the Sequence __call()
method use:
Aimeos Upscheme Schema Sequence:: marco ( ' test ' , function () {
// $this - >db : Upscheme DB object
// $this - >sequence : Doctrine Sequence object
// return $this or a value
} );
$ sequence -> test ();
Instead of calling the col()
method of the Table object with all parameters and modifiers each time, you can create your own shortcut methods, eg:
Aimeos Upscheme Schema Table:: marco ( ' utinyint ' , function ( string $ name ) {
return $ this -> col ( $ name , ' tinyint ' )-> unsigned ( true );
} );
It's also possible to create several columns at once if you want to add them to several tables:
Aimeos Upscheme Schema Table:: marco ( ' defaults ' , function () {
$ this -> id ();
$ this -> datetime ( ' ctime ' );
$ this -> datetime ( ' mtime ' );
$ this -> string ( ' editor ' );
return $ this ;
} );
Then, use your custom methods when creating or updating tables:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
$ table -> defaults ();
$ table -> utinyint ( ' status ' );
} );
Version 0.9+ supports Doctrine DBAL 3.x/4.x and dropped support for Doctrine DBAL 2.x.
DB::type()
returns mariadb
instead of mysql
for MariaDDB databaseDB::type()
returns sqlserver
instead of mssql
for Microsoft SQLServer databaseDB::for()
, DB::view()
and Column::opt
require ['mariadb', 'mysql']
to get the same resultsDB::lastId()
doesn't require/support passing a sequence name because Doctrine DBAL removed it but doesn't support Oracle IDENTITY columns at the moment