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.
Cake\Database\Schema\
TableSchema
¶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.
Cake\Database\Schema\
Collection
¶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');