O CakePHP possui um sistema de schema que é capaz de refletir e gerar informaçes de schema para tabelas em SQL datastores. O sistema de schema pode gerar/refletir schema para qualquer plataforma que o CakePHP suporte.
As partes principais do sistema de schema são Cake\Database\Schema\Collection
e Cake\Database\Schema\TableSchema
. Essas classes te oferecem acesso a
todo o banco de dados e recursos de tabela individual respectivamente.
O uso primário de sistema de schema é para Fixtures. No entanto, isso também ser usado em sua aplicação se requerido.
O subsistema de schema oferece um simples objeto TableSchema para guardar dados sobre uma tabela do banco de dados. Este objeto é retornado pelos recursos de reflexão de schema:
use Cake\Database\Schema\TableSchema;
// Criar uma tabela, uma coluna por vez.
$schema = new TableSchema('posts');
$schema->addColumn('id', [
'type' => 'integer',
'length' => 11,
'null' => false,
'default' => null,
])->addColumn('title', [
'type' => 'string',
'length' => 255,
// Cria um campo de tamanho fixo (char field)
'fixed' => true
])->addConstraint('primary', [
'type' => 'primary',
'columns' => ['id']
]);
// Classes Schema\TableSchema também podem ser criados com array de dados
$schema = new TableSchema('posts', $columns);
Objetos Schema\TableSchema
permitem você construir apartir de informações sobre schema de tabelas.
Isto ajuda a normalizar e validar os dados usados para descrever uma tabela. Por exemplo, as duas formas
a seguir são equivalentes:
$schema->addColumn('title', 'string');
// e
$schema->addColumn('title', [
'type' => 'string'
]);
Enquanto equivalete, a 2ª forma permite mais detalhes e controle. Isso emula os recursos existentes disponíveis em arquivos de Schema + os schema de fixture em 2.x.
Colunas são adicionadas como argumentos do construtor, ou pelo método addColumn(). Uma vez que os campos são adicionados, as informações podem ser obtidas usando o método column() ou columns():
// Obtem um array de dados sobre a coluna
$c = $schema->column('title');
// Obtem uma lista com todas as colunas.
$cols = $schema->columns();
Os índices são adicionado usando addIndex()
. Restrições são adicionadas
usando addConstraint()
. Os índices e restriçes não podem ser adicionados
para colunas que não existem, já que isso resultaria em um estado ínvalido.
Os índices são difentes de restrições, e exceções serão disparadas se você
tentar misturar tipos entre os métodos. Um exemplo de ambos os métodos é:
$schema = new TableSchema('posts');
$schema->addColumn('id', 'integer')
->addColumn('author_id', 'integer')
->addColumn('title', 'string')
->addColumn('slug', 'string');
// Adiciona uma chave primária.
$schema->addConstraint('primary', [
'type' => 'primary',
'columns' => ['id']
]);
// Adiciona uma chave única
$schema->addConstraint('slug_idx', [
'columns' => ['slug'],
'type' => 'unique',
]);
// Adiciona um index
$schema->addIndex('slug_title', [
'columns' => ['slug', 'title'],
'type' => 'index'
]);
// Adiciona uma chave estrangeira
$schema->addConstraint('author_id_idx', [
'columns' => ['author_id'],
'type' => 'foreign',
'references' => ['authors', 'id'],
'update' => 'cascade',
'delete' => 'cascade'
]);
Se você adicionar uma restrição de chave primária para uma coluna do tipo integer, ela será automaticamente convertida em uma coluna auto-increment/serial dependendo da plataforma de banco de dados:
$schema = new TableSchema('posts');
$schema->addColumn('id', 'integer')
->addConstraint('primary', [
'type' => 'primary',
'columns' => ['id']
]);
No exemplo abaixo a coluna id
geraria o seguinte SQL em MySQL:
CREATE TABLE `posts` (
`id` INTEGER AUTO_INCREMENT,
PRIMARY KEY (`id`)
)
Se sua chave primária contêm mais que uma coluna, nenhuma delas serão automaticamente convertidas para um valor auto-incremento. Em vez disso, você precisará dizer ao objeto da tabela qual coluna na chave composta que você deseja usar auto-incremento:
$schema = new TableSchema('posts');
$schema->addColumn('id', [
'type' => 'integer',
'autoIncrement' => true,
])
->addColumn('account_id', 'integer')
->addConstraint('primary', [
'type' => 'primary',
'columns' => ['id', 'account_id']
]);
A opção autoIncrement
apenas funciona com colunas do tipo integer
e biginteger
.
Os índices e restrições podem ser lido de um objeto de tabela usando métodos
acessores. Assumindo que $schema
é uma instância de TableSchema populada, você poderia
fazer o seguinte:
// Obter restrições. Retornará os
// nomes de todas as restrições.
$constraints = $schema->constraints()
// Obter dados sobre uma restrição.
$constraint = $schema->constraint('author_id_idx')
// Obter índices. Retornará os
// nomes de todos os índices
$indexes = $schema->indexes()
// Obter dados sobre um índice
$index = $schema->index('author_id_idx')
Alguns drivers (principalmente MySQL) suportam e requerem metadados de tabela
adicionais. No caso do MySQL as propriedades CHARSET
, COLLATE
e ENGINE
são requeridos para manter a estrutura de uma tabela no MySQL. O seguinte
pode ser usado para adicionar opções de tabela:
$schema->options([
'engine' => 'InnoDB',
'collate' => 'utf8_unicode_ci',
]);
Os dialetos de plataforma apenas cuidam das chaves que eles estão interessados e ignoram o resto. Nem todas as opções são suportadas por todas as plataformas.
Usando os métodos createSql()
ou dropSql()
você pode obter
SQL específico de plataforma para criar ou remover uma tabela específica:
$db = ConnectionManager::get('default');
$schema = new TableSchema('posts', $fields, $indexes);
// Criar uma tabela
$queries = $schema->createSql($db);
foreach ($queries as $sql) {
$db->execute($sql);
}
// Remover um tabela
$sql = $schema->dropSql($db);
$db->execute($sql);
Ao usar o driver de conexão, os dados de schema podem ser convertidos em
SQL específico da plataforma. O retorno de createSql
e dropSql
é uma
lista de consultas SQL requeridas para criar uma tabela e os indices.
Algumas plataformas podem requerer várias declaraçes para criar tabelas com
comentários e/ou índices. Um array de consultas SQL é sempre retornado.
Collection
fornece acesso as várias tabelas disponíveis numa conexão.
Você pode usar isto para obter a lista de tabelas ou refletir tabelas em
objetos TableSchema
. O uso básico da classe parece com:
$db = ConnectionManager::get('default');
// Criar uma coleção de schema.
// Prior to 3.4 use $db->schemaCollection()
$collection = $db->getSchemaCollection();
// Obtem os nomes das tabelas.
$tables = $collection->listTables();
// Obtem uma tabela específica (instância de Schema\TableSchema)
$tableSchema = $collection->describe('posts');