3.7.6.6 Criando e removendo relações durante execução

Por vezes, torna-se necessário criar e destruir associações no modelo durante a execução. Isso pode acontecer por algum número de razões:

  • Você deseja reduzir a quantidade coletada de dados associados, mas todas as suas associações estão no primeiro nível de recursão.
  • Você quer mudar o modo como uma associação é definida, a fim de ordenar ou filtrar dados associados.

Esta criação e destruição de associação é feita usando os métodos bindModel() e unbindModel() do modelo CakePHP. Vamos configurar alguns modelos, para que possamos ver como bindModel() e unbindModel() trabalham. Nós vamos começar com dois modelos:

<?php

class Leader extends AppModel {
    var $name = 'Leader';

    var $hasMany = array(
        'Follower' => array(
            'className' => 'Follower',
            'order'     => 'Follower.rank'
        )
    );
}

?>

<?php

class Follower extends AppModel {
    var $name = 'Follower';
}

?>
  1. <?php
  2. class Leader extends AppModel {
  3. var $name = 'Leader';
  4. var $hasMany = array(
  5. 'Follower' => array(
  6. 'className' => 'Follower',
  7. 'order' => 'Follower.rank'
  8. )
  9. );
  10. }
  11. ?>
  12.  
  13. <?php
  14. class Follower extends AppModel {
  15. var $name = 'Follower';
  16. }
  17. ?>

Agora, no LeadersController, podemos usar o método find() do modelo Leader para buscar um líder e seus seguidores associados. Como você pode ver acima, a associação em sintaxe de array no modelo Leader define um relacionamento "Leader hasMany Follower". Para fins de demonstração, vamos usar unbindModel() para remover esta associação em uma função do controlador.

function someAction() {
    // Isto recupera Líderes, e seus seguidores associados
    $this->Leader->findAll();

    // Vamos remover o hasMany...
    $this->Leader->unbindModel(
        array('hasMany' => array('Follower'))
    );

    // Agora usando a função find() irá retornar
    // Líderes, sem os seus seguidores
    $this->Leader->findAll();

    // NOTA: unbindModel() afeta somente a mais próxima
    // função find(). Uma nova chamada find() será usada
    // a informação configurada na associação do modelo.

    // Já utilizando findAll(), após unbindModel(),
    // esta vai buscar Líderes com seguidores
    // associados mais uma vez...
    $this->Leader->findAll();
}
  1. function someAction() {
  2. // Isto recupera Líderes, e seus seguidores associados
  3. $this->Leader->findAll();
  4. // Vamos remover o hasMany...
  5. $this->Leader->unbindModel(
  6. array('hasMany' => array('Follower'))
  7. );
  8. // Agora usando a função find() irá retornar
  9. // Líderes, sem os seus seguidores
  10. $this->Leader->findAll();
  11. // NOTA: unbindModel() afeta somente a mais próxima
  12. // função find(). Uma nova chamada find() será usada
  13. // a informação configurada na associação do modelo.
  14. // Já utilizando findAll(), após unbindModel(),
  15. // esta vai buscar Líderes com seguidores
  16. // associados mais uma vez...
  17. $this->Leader->findAll();
  18. }

Mais um lembrete. Removendo ou adicionando associações usando bind e unbindModel() só funciona para a próxima operação do modelo, a menos que o segundo parâmetro $reset for escolhido para true. Se o segundo parâmetro foi escolhido para true, ao vincular este parâmetro, a funções binds, mantém-se em vigor para o restante dos pedidos ou pesquisas. Aqui está a base para o uso padrão de unbindModel():

$this->Model->unbindModel(
    array('associationType' => array('associatedModelClassName'))
);

// associationType => O tipo de associação com o outro modelo (associatedModelClassName) que você quer remover.
  1. $this->Model->unbindModel(
  2. array('associationType' => array('associatedModelClassName'))
  3. );
  4. // associationType => O tipo de associação com o outro modelo (associatedModelClassName) que você quer remover.

Agora que removida com êxito uma associação durante a execução, vamos adicionar uma. Nossa como de ainda temos Líderes sem princípios necessitamos alguns Princípios associados. O arquivo do modelo para o nosso modelo Principle está vazio, com exceção para a declaração var $name. Vamos associar alguns princípios para ao nosso modelo Leader durante a execução (mas lembre-apenas servirá a próxima operação de busca). Esta função aparece no LeadersController:

function anotherAction() {
    // Não há "Leader hasMany Principles" no
    // the leader.php model file, so a find here, arquivo do modelo leader.php,
    // aqui somente vamos encontrar Líderes.
    $this->Leader->findAll();

    // Vamos usar bindModel() para adicionar uma nova associação
    // para o modelo Leader.
    $this->Leader->bindModel(
        array('hasMany' => array(
                'Principle' => array(
                    'className' => 'Principle'
                )
            )
        )
    );

    // Agora que está ligado corretamente,
    // Podemos utilizar uma única função find() para buscar
    // Líderes com seus associados princípios:
    $this->Leader->findAll();
}
  1. function anotherAction() {
  2. // Não há "Leader hasMany Principles" no
  3. // the leader.php model file, so a find here, arquivo do modelo leader.php,
  4. // aqui somente vamos encontrar Líderes.
  5. $this->Leader->findAll();
  6. // Vamos usar bindModel() para adicionar uma nova associação
  7. // para o modelo Leader.
  8. $this->Leader->bindModel(
  9. array('hasMany' => array(
  10. 'Principle' => array(
  11. 'className' => 'Principle'
  12. )
  13. )
  14. )
  15. );
  16. // Agora que está ligado corretamente,
  17. // Podemos utilizar uma única função find() para buscar
  18. // Líderes com seus associados princípios:
  19. $this->Leader->findAll();
  20. }

Isto é o que você tem. A base para uso do bindModel() é o encapsulamento de uma associação normal dentro de um array cuja chave é nomeada após o tipo de associação que você está tentando criar:

$this->Model->bindModel(
        array('associationName' => array(
                'associatedModelClassName' => array(
                    // Aqui você pode usar normalmente as chaves e/ou opções de associação.
                )
            )
        )
    );
  1. $this->Model->bindModel(
  2. array('associationName' => array(
  3. 'associatedModelClassName' => array(
  4. // Aqui você pode usar normalmente as chaves e/ou opções de associação.
  5. )
  6. )
  7. )
  8. );

Embora o modelo recém-vinculado não precise de nenhum tipo de associação na definição do modelo dentro do arquivo dele, ele ainda precisa ser introduzido corretamente para que a nova associação funcione corretamente.