CakePHP 提供了一个架构系统,能够反映和生成 SQL 数据存储中表格的架构信息。架构系统可以为 CakePHP 支持的任何 SQL 平台生成/反映架构。
架构系统的主要部分是 Cake\Database\Schema\Collection
和 Cake\Database\Schema\TableSchema
。这些类分别为您提供了对数据库范围和单个表格对象功能的访问。
架构系统的主要用途是用于 测试夹具。但是,如果需要,也可以在您的应用程序中使用它。
架构子系统提供了一个简单的 TableSchema 对象来保存有关数据库中表格的数据。此对象由架构反射功能返回。
use Cake\Database\Schema\TableSchema;
// Create a table one column at a time.
$schema = new TableSchema('posts');
$schema->addColumn('id', [
'type' => 'integer',
'length' => 11,
'null' => false,
'default' => null,
])->addColumn('title', [
'type' => 'string',
'length' => 255,
// Create a fixed length (char field)
'fixed' => true
])->addConstraint('primary', [
'type' => 'primary',
'columns' => ['id']
]);
// Schema\TableSchema classes could also be created with array data
$schema = new TableSchema('posts', $columns);
Schema\TableSchema
对象允许您构建有关表格架构的信息。它有助于规范和验证用于描述表格的数据。例如,以下两种形式是等效的。
$schema->addColumn('title', 'string');
// and
$schema->addColumn('title', [
'type' => 'string'
]);
虽然等效,但第二种形式允许更多细节和控制。这模拟了 2.x 中 Schema 文件 + 测试夹具架构中可用的现有功能。
列作为构造函数参数添加,或通过 addColumn() 添加。一旦字段被添加,可以使用 column() 或 columns() 获取信息。
// Get the array of data about a column
$c = $schema->column('title');
// Get the list of all columns.
$cols = $schema->columns();
索引使用 addIndex()
添加。约束使用 addConstraint()
添加。索引和约束不能为不存在的列添加,因为这会导致无效状态。索引不同于约束,如果您尝试在方法之间混合类型,将会引发异常。以下两个方法的示例:
$schema = new TableSchema('posts');
$schema->addColumn('id', 'integer')
->addColumn('author_id', 'integer')
->addColumn('title', 'string')
->addColumn('slug', 'string');
// Add a primary key.
$schema->addConstraint('primary', [
'type' => 'primary',
'columns' => ['id']
]);
// Add a unique key
$schema->addConstraint('slug_idx', [
'columns' => ['slug'],
'type' => 'unique',
]);
// Add index
$schema->addIndex('slug_title', [
'columns' => ['slug', 'title'],
'type' => 'index'
]);
// Add a foreign key
$schema->addConstraint('author_id_idx', [
'columns' => ['author_id'],
'type' => 'foreign',
'references' => ['authors', 'id'],
'update' => 'cascade',
'delete' => 'cascade'
]);
如果您将主键约束添加到单个整型列,它将根据数据库平台自动转换为自增/序列列。
$schema = new TableSchema('posts');
$schema->addColumn('id', 'integer')
->addConstraint('primary', [
'type' => 'primary',
'columns' => ['id']
]);
在上面的示例中,id
列将在 MySQL 中生成以下 SQL。
CREATE TABLE `posts` (
`id` INTEGER AUTO_INCREMENT,
PRIMARY KEY (`id`)
)
如果您的主键包含多个列,那么它们都不会自动转换为自增值。相反,您需要告诉表格对象要将哪个复合键列设置为自增。
$schema = new TableSchema('posts');
$schema->addColumn('id', [
'type' => 'integer',
'autoIncrement' => true,
])
->addColumn('account_id', 'integer')
->addConstraint('primary', [
'type' => 'primary',
'columns' => ['id', 'account_id']
]);
autoIncrement
选项仅适用于 integer
和 biginteger
列。
可以使用访问器方法从表格对象中读取索引和约束。假设 $schema
是一个已填充的 TableSchema 实例,您可以执行以下操作。
// Get constraints. Will return the
// names of all constraints.
$constraints = $schema->constraints()
// Get data about a single constraint.
$constraint = $schema->constraint('author_id_idx')
// Get indexes. Will return the
// names of all indexes.
$indexes = $schema->indexes()
// Get data about a single index.
$index = $schema->index('author_id_idx')
一些驱动程序(主要是 MySQL)支持并需要额外的表格元数据。在 MySQL 的情况下,CHARSET
、COLLATE
和 ENGINE
属性是维护 MySQL 中表格结构所必需的。可以使用以下方法添加表选项。
$schema->options([
'engine' => 'InnoDB',
'collate' => 'utf8_unicode_ci',
]);
平台方言只处理它们感兴趣的键,而忽略其余的键。并非所有选项都在所有平台上都受支持。
使用 createSql()
或 dropSql()
,您可以获取特定平台的 SQL 代码,用于创建或删除特定表格。
$db = ConnectionManager::get('default');
$schema = new TableSchema('posts', $fields, $indexes);
// Create a table
$queries = $schema->createSql($db);
foreach ($queries as $sql) {
$db->execute($sql);
}
// Drop a table
$sql = $schema->dropSql($db);
$db->execute($sql);
通过使用连接的驱动程序,架构数据可以转换为特定平台的 SQL 代码。createSql
和 dropSql
的返回值是创建表格和所需索引所需的 SQL 查询列表。一些平台可能需要多个语句来创建带有注释和/或索引的表格。始终返回一个查询数组。
Collection
提供了对连接中可用表格的访问。您可以使用它来获取表格列表或将表格反映到 TableSchema
对象中。类的基本用法如下所示。
$db = ConnectionManager::get('default');
// Create a schema collection.
$collection = $db->getSchemaCollection();
// Get the table names
$tables = $collection->listTables();
// Get a single table (instance of Schema\TableSchema)
$tableSchema = $collection->describe('posts');