CakePHP 3 e relacionamentos entre tabelas Artigo

Conheça os cursos gratuitos do WebDevBr! - Inscreva-se!


Este artigo foi publicado a 2 anos, 5 meses, 1 semana, 4 dias atrás.

O artigo de número 100 não poderia deixar de ser sobre CakePHP, e desta vez quero falar um pouco sobre relacionamentos entre tabelas, um assunto que tira o sono de muita gente, vamos ver?

hasOne - Um para um

O relacionamento hasOne informa que um registro está relacionado a apenas um outro registro, por exemplo, um usuário pode ter apenas um perfil em uma rede social.

Para definir um relacionamento hasOne vá até o método initialize() do Table em questão, por exemplo o UsersTable (em app/Model/Table/UsersTable.php).

Gostou deste artigo?

Receba atualizações semanais com novos artigos do WebDevBr e outras dicas!

namespace App\Model\Table;

use Cake\ORM\Table;

class UsersTable extends Table
{

    public function initialize(array $config)
    {
        $this->hasOne('Profile');
    }

}

A tabela profiles (que é a relacionada) deverá ter um campo chamado user_id, entendeu? nomes de tabelas no plural, e a foreing key (chave estrageira) no singular. Para não se perder você pode informar qual será sua chave estrangeira, e não usar esta regra.

namespace App\Model\Table;

use Cake\ORM\Table;

class UsersTable extends Table
{

    public function initialize(array $config)
    {
        $this->hasOne('Profile', [
            'foreignKey' => 'user_id'
        ]);
    }

}

Para ver mais opções para hasOne visite este link.

hasMany - Um para muitos

O relacionamento hasMany informa que um registro está relacionado a vários outro registros, por exemplo, um usuário pode ter várias fotos em uma rede social.

Para definir um relacionamento hasMany vá até o método initialize() do Table em questão, por exemplo o UsersTable (em app/Model/Table/UsersTable.php).

namespace App\Model\Table;

use Cake\ORM\Table;

class UsersTable extends Table
{

    public function initialize(array $config)
    {
        $this->hasMany('Photos');
    }

}

Bem parecido com o hasOne, só que agora quem recebe a chave estrangeira userid é a tabela photos, neste caso também é possível personalizar a chave estrangeira usando o 'foreignkey' dentro do array no segundo parâmetro, para ver as outras opções vá até este link.

belongsTo - O contrário de hasOne e hasMany

O relacionamento belongsTo acontece naturalmente na lógica da aplicação, se você cria um relacionamento hasOne e/ou hasMany é natural que a outra tabela também se relacione, mas mesmo assim ele tem que ser informado.

Para definir um relacionamento belongsTo vá até o método initialize() do Table em questão, por exemplo o PhotosTable (em app/Model/Table/PhotosTable.php).

namespace App\Model\Table;

use Cake\ORM\Table;

class PhotosTable extends Table
{

    public function initialize(array $config)
    {
        $this->belongsTo('Users');
    }

}

Nenhuma novidade, só que agora quem recebe a chave estrangeira userid é a tabela do model que estamos (tabela photos), neste caso também é possível personalizar a chave estrangeira usando o 'foreignkey' dentro do array no segundo parâmetro, para ver as outras opções vá até este link.

BelongsToMany - Muitos para muitos

O relacionamento belongsToMany informa que vários registro estam relacionado a vários outros registros, por exemplo, um usuário pode ter várias grupos, e vários grupos podem ter vários usuários em uma rede social..

Para definir um relacionamento belongsToMany vá até o método initialize() do Table em questão, por exemplo o GroupsTable (em app/Model/Table/GroupsTable.php).

namespace App\Model\Table;

use Cake\ORM\Table;

class GroupsTable extends Table
{

    public function initialize(array $config)
    {
        $this->belongsToMany('Users');
    }

}

A novidade agora é que a chave estrageira fica dentro de uma terceira tabela cujo nome é formado pelo nome das outras duas, em ordem alfabética e separado por hifen, neste exemplo ela se chamaria 'groupsusers', esta tabela tem 3 campos, id, e as chaves estrangeiras de ambas as tabelas, neste caso, userid e group_id. Da pra personalizar o nome da "tabela de junção" e das chaves estrangeiras, veja:

namespace App\Model\Table;

use Cake\ORM\Table;

class GroupsTable extends Table
{

    public function initialize(array $config)
    {
        $this->belongsToMany('Users', [
            'joinTable' => 'article_tag',
            'foreignKey' => 'group_id',
            'targetForeignKey'=>'user_id'
        ]);
    }

}

Agora temos o joinTable (nome da tabela de junção), a foreign key (chave estrangeira do model atual) e a target foreign key (chave estrangeira do model relacionado), vale reforçar que o model relacionado deverá ter as mesmas configurações (com as devidas alterações em foreignKey e targetForeignKey). Para ver mais opções de uma olhada neste link.

Usando o model relacionado

Todos os dados relacionados são trazidos quando você faz alguma busca no model em questão (users, por exemplo) e isso pode ser manipulado com a configuração contain, existem várias formas de usar, então de uma olhada nos exemplos da documentação.

Além disso você pode executar as buscas direto no model relacionado ou salvar qualquer informação acessando diretamente a partir do model atual, exemplo:

$groups = $this->Users->Groups->find('list');

Essa variável $groups vai trazer uma lista de grupos que você pode colocar em um options por exemplo (passando com $this->set('groups', $groups)).

Da pra salvar dados ou fazer o que quiser com o model Groups carregado direto do Users.

Isso está disponível da mesma forma para qualquer tipo de relacionamento.

Formulários

Para os relacionamentos hasOne, hasMany e belongsTo você só precisa cria um campo com os dados da lista do exemplo anterior, na verdade se passar o nome da variável no plural (como eu fiz acima)  o CakePHP pega estes dados automáticamente.

echo $this->Form->input('group_id');

Claro que por algum motivo isso pode não funcionar como deveria, então você pode setar o campo.

echo $this->Form->input('group_id', ['options' => $groups]);

Já o campo para o belongsToMany deveria ser:

echo $this->Form->input('groups._ids', ['options' => $groups]);

Muito simples não? Aqui a documentação sobre o assunto.

Salvando os dados

Para salvar (atualizar ou criar) 1 nível de associação é fácil, só usar o save normalmente, veja alguns exemplos.

E para salvar belongsToMany.

Conclusão

É muito fácil trabalhar com relacionamentos usando o CakePHP 3, não tem segredo algum, uma rápida olhada em cada sessão correspondente (Associations, Saving Data e Form) da documentação e você já vira mestre.


Cursos relacionados


* Parcelamento apenas cartão de crédito! Pode haver uma pequena variação no parcelamento em relação a simulações apresentadas!