易於使用的 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(真) | 允許將空值插入列 |
精度(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 |
charset() | 二手字元集(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
此選項應用於(“ 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 ' ] );
} );
In all cases, indexes are only renamed if they exist. No error is reported if one or more indexes doesn't exist in the table.
To drop indexes, use the dropIndex()
method from the DB schema object:
$ this -> db ()-> dropIndex ( ' users ' , ' idx_test_name ' );
You can drop several indexes at once if you pass the name of all indexes you want to drop as array:
$ this -> db ()-> dropIndex ( ' users ' , [ ' idx_test_name ' , ' idx_test_status ' ] );
If you already have a table object, you can use dropIndex()
too:
$ this -> db ()-> table ( ' test ' , function ( $ table ) {
// single index
$ table -> dropIndex ( ' idx_test_name ' );
// multiple indexes
$ table -> dropIndex ( [ ' idx_test_name ' , ' idx_test_status ' ] );
} );
In all cases, indexes are only removed if they exist. 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