Welcome to the Cookbook

loading...

3.7.4.2 Salvando dados em tabelas relacionadas (HABTM)

The original text for this section has changed since it was translated. Please help resolve this difference. You can:

More information about translations

Salvar models que são associados por hasOne, blongsTo e hasMany é muito simples: você apenas popula seu campo de chave estrangeira com o ID do model associado. Uma vez isso feito, você apenas chama o método save() no model, e tudo se linka corretamento.

Com HABTM (has_and_belong_to_many), você precisa definir o ID do model associado em seu array de dados. Nós contruiremos um formulário que cria uma nova tag e a associa "na mosca"com alguma receita.

O formulário simples parece com algum como isto (assumimos que $recipe_id já está definido a algo):

<?php echo $form->create('Tag');?>
<?php echo $form->input(
    'Recipe.id',  // Recipe significa receita
     array('type'=>'hidden', 'value' => $recipe_id)); ?>
<?php echo $form->input('Tag.name'); ?>
<?php echo $form->end('Add Tag'); ?>
  1. <?php echo $form->create('Tag');?>
  2. <?php echo $form->input(
  3. 'Recipe.id', // Recipe significa receita
  4. array('type'=>'hidden', 'value' => $recipe_id)); ?>
  5. <?php echo $form->input('Tag.name'); ?>
  6. <?php echo $form->end('Add Tag'); ?>

Neste exemplo, você pode ver o campo oculto Recipe.id o qual o valor é definido para o ID da receita que queremos linkar a tag.

Quando o método save() é invocado dentro do controller, ele automaticamente salva o os dados HABTM no banco de dados.

function add() {
    
    //Salva a associação
    if ($this->Tag->save($this->data)) {
        //faz algo se salvo com sucesso
    }
}
  1. function add() {
  2. //Salva a associação
  3. if ($this->Tag->save($this->data)) {
  4. //faz algo se salvo com sucesso
  5. }
  6. }

Como o código anterior, nossa nova Tag é criada e associada a Recipe (receita), do qual o ID foi definido em $this ->data['Recipe']['id'].

Outras formas que podemos querer apresentar nossos dados associados pode incluir uma lista select drop down. Os dados podem ser puxados do model usando o método find('list') e enviado a uma váriavel da view do nome do model. Um campo com o mesmo nome será automaticamente puxado com estes dados dentro de uma <select>.

// no controller:
$this->set('tags', $this->Recipe->Tag->find('list'));

// na view:
$form->input('tags');
  1. // no controller:
  2. $this->set('tags', $this->Recipe->Tag->find('list'));
  3. // na view:
  4. $form->input('tags');

Um cenário mais provável com um relacionamento HABTM deve incluir <select> definido para aceitar múltiplas seleções. Por exemplo, uma Receita por ter múltiplas Tags atribuídas a ela. Neste caso, os dados são puxados do model da mesma maneira, mas o campo do formulário é declarado ligeiramente diferente. O nome da tag é definidos usando a convenção ModelName.

// no controller:
$this->set('tags', $this->Recipe->Tag->find('list'));

// na view:
$form->input('Tag');
  1. // no controller:
  2. $this->set('tags', $this->Recipe->Tag->find('list'));
  3. // na view:
  4. $form->input('Tag');

Usando o código anterior, uma campo select dorp down múltiplo é criado, permitindo que múltiplas escolhas sejam automaticamente salvas às Receitas existentes sendo adicionada ou salva no banco de dados

O que fazer quando HABTM se torna complicado?

Por padrão ao salvar um relacionamento HasAndBelongsToMany, o CakePHP excluirá todas as linhas na tabela juntada antes de salvar novas. Por exemplo se você tem um Clube que tem 10 Crianças associadas. Você depois atualiza o Clube com 2 crianças. O Clube setá apenas 2 Crianças, não 12.

Também note que se você quer adicionar mais campos ao juntamento (quando ele foi criado ou meta informação)isto é possivelmente com tabelas juntadas HABTM, mas é importante entender que uma opção fácil.

HasAndBelongsToMany entre dois models é na verdade um atalho para três models associados entre ambos uma associação hasMany e uma belongsTo.

Considere este exemplo:

Child hasAndBelongsToMany Club
  1. Child hasAndBelongsToMany Club

Outra forma de olhar para isto é adicionando um model Membership:

Child hasMany Membership
Membership belongsTo Child, Club
Club hasMany Membership.
  1. Child hasMany Membership
  2. Membership belongsTo Child, Club
  3. Club hasMany Membership.

Estes dois exemplos são exatamente o mesmo. Eles usam o mesmo valor e nomes de campos no banco de dados e o mesmo valor de models. A diferença importante é que o modelo juntado está nomeado diferentemente e seu comportamento é mais previsível.