3.7.6.5 hasAndBelongsToMany (HABTM)
Tudo bem. Neste ponto, você já pode chamar você mesmo de profissional em associações de modelos no CakePHP. Você já está bem versado(experiente) nas três associações que ocupam a maior parte das relações entre objetos.
Vamos resolver o último tipo de relacionamento: hasAndBelongsToMany, ou HABTM. Esta associação é usada quando você tem dois modelos que precisam se juntar, várias vezes, muitas vezes, de muitas formas diferentes.
A principal diferença entre hasMany e HABTM é que a ligação entre os modelos em HABTM não é exclusiva. Por exemplo, estamos prestes a juntar nosso modelo Recipe(Receita) com o modelo Tag usando HABTM. Anexando a tag “Italian” a minha receita “grandma's Gnocci” não “esgota” o registro do Tag. Também posso marcar o meu churrasco Honey Glazed Spaghettio's com a tag “Italian” se eu quiser.
Ligações entre objetos associados com hasMany são exclusivos. Se User hasMany Comment, um comentário é apenas ligado a um usuário específico. Deixou-se para ganhar.
Avancemos. É preciso criar uma tabela extra no banco de dados para manipular associações HABTM. Esta nova tabela deve juntar o nome das tabelas associadas, incluindo os nomes de ambos os modelos envolvidos, em ordem alfabética. O conteúdo da tabela deve ser de pelo menos dois campos, cada um com uma chave estrangeira (que devem ser inteiros) apontando para ambas as chaves primárias dos modelos envolvidos.
HABTM: Requer uma tabela separada que inclue os dois nomes dos modelos. Nota: O nome da tabela deve estar em ordem alfabética. Recipe HABTM Tag => recipes_tags.recipe_id, recipes_tags.tag_id Cake HABTM Fan => cakes_fans.cake_id, cakes_fans.fan_id Foo HABTM Bar => bars_foos.foo_id, bars_foos.bar_id
HABTM: Requer uma tabela separada que inclue os dois nomes dos modelos.Nota: O nome da tabela deve estar em ordem alfabética.Recipe HABTM Tag => recipes_tags.recipe_id, recipes_tags.tag_idCake HABTM Fan => cakes_fans.cake_id, cakes_fans.fan_idFoo HABTM Bar => bars_foos.foo_id, bars_foos.bar_id
Uma vez que esta nova tabela foi criada, podemos definir a associação HABTM nos arquivos dos modelos. Estamos indo saltar diretamente a sintaxe array desta vez:
<?php
class Recipe extends AppModel {
var $name = 'Recipe';
var $hasAndBelongsToMany = array(
'Tag' =>
array('className' => 'Tag',
'joinTable' => 'posts_tags',
'foreignKey' => 'recipe_id',
'associationForeignKey' => 'tag_id',
'conditions' => '',
'order' => '',
'limit' => '',
'uniq' => true,
'finderQuery' => '',
'deleteQuery' => '',
'insertQuery' => ''
)
);
}
?>
<?phpclass Recipe extends AppModel {var $name = 'Recipe';var $hasAndBelongsToMany = array('Tag' =>array('className' => 'Tag','joinTable' => 'posts_tags','foreignKey' => 'recipe_id','associationForeignKey' => 'tag_id','conditions' => '','order' => '','limit' => '','uniq' => true,'finderQuery' => '','deleteQuery' => '','insertQuery' => ''));}?>
As possíveis chaves do array para associações hasAndBelongsToMany são:
- className: o nome da classe do modelo a ser associado ao modelo atual. Se você estiver definindo um relacionamento “Recipe HABTM Tag” , a chave className deve ser igual “Tag”.
- joinTable: O nome da tabela usada para ingressar nesta associação (se a atual tabela usada para fazer esse tipo de relacionamento não aderir à convenção citada acima para nomear tabelas HABTM).
- foreignKey: O nome da chave estrangeira encontrada no outro modelo. Isto é especialmente útil se você precisa definir múltiplos relacionamentos HABTM. O valor padrão para esta chave é o nome do outro modelo no singular, seguida de “_id”.
- associationForeignKey: O nome da chave estrangeira encontrada no modelo atual. Isto é especialmente útil se você precisa definir múltiplos relacionamentos HABTM. O valor padrão para esta chave é o nome do atual modelo no singular, seguida de '_id'.
- conditions: Um fragmento SQL utilizado para filtrar registros no modelo relacionado. É uma boa prática a utilização nome do modelo nos fragmentos SQL: “Recipe.status = 1” é sempre melhor do que apenas “status = 1”.
- fields: A lista de campos a serem recuperados quando os dados do modelo associado são coletados. Retorna todos os campos por padrão.
- order: Um fragmento SQL que define a classificação para a ordem para o retorno de linhas associadas.
- limit: O número máximo de linhas associadas que você quer que retorne.
- offset: O número de linhas associadas para saltar sobre (dadas as atuais condições e ordem), antes de ir buscar e associar.
- finderQuery, deleteQuery, insertQuery: Uma completa consulta SQL CakePHP que pode-se usar para buscar registros associados. Isto deve ser utilizado em situações que exijam muito resultado personalizado.
Uma vez que esta associação tenha sido definida, operações de busca sobre o modelo Recipe(Receita) também vai buscar registros relacionados em Tag caso existam:
// Exemplo de resultados de uma chamada $this->Recipe->find();
Array
(
[Recipe] => Array
(
[id] => 2745
[name] => Chocolate Frosted Sugar Bombs
[created] => 2007-05-01 10:31:01
[user_id] => 2346
)
[Tag] => Array
(
[0] => Array
(
[id] => 123
[name] => Breakfast
)
[1] => Array
(
[id] => 123
[name] => Dessert
)
[2] => Array
(
[id] => 123
[name] => Heart Disease
)
)
)
// Exemplo de resultados de uma chamada $this->Recipe->find();Array([Recipe] => Array([id] => 2745[name] => Chocolate Frosted Sugar Bombs[created] => 2007-05-01 10:31:01[user_id] => 2346)[Tag] => Array([0] => Array([id] => 123[name] => Breakfast)[1] => Array([id] => 123[name] => Dessert)[2] => Array([id] => 123[name] => Heart Disease)))
Lembre-se de definir uma associação HABTM no modelo Tag se quiser buscar dados do modelo Recipe, quando se utiliza o modelo Tag para pesquisas.
