Como faço para participar de duas tabelas em um relacionamento terceiro n..n (hasAndBelongsToMany) em CakePHP?

StackOverflow https://stackoverflow.com/questions/112730

Pergunta

Eu tenho uma estrutura n...n para duas tabelas, makes e models . Até agora não há problema.

Em uma terceira tabela ( products ) como:

id
make_id
model_id
...

Meu problema é a criação de uma exibição para produtos de uma específi make dentro da minha ProductsController contendo apenas isso de fazer modelos:

Eu pensei que isso poderia funcionar:

var $uses = array('Make', 'Model');

$this->Make->id = 5; // My Make

$this->Make->find(); // Returns only the make I want with it's Models (HABTM)
$this->Model->find('list'); // Returns ALL models
$this->Make->Model->find('list'); // Returns ALL models

Então, se eu quiser usar o list para passar para meu ponto de vista para criar botões de rádio que vou ter que fazer uma foreach() na minha make array para encontrar todos os modelos títulos e criar uma nova matriz e enviar para a view via $this->set().

$makeArray = $this->Make->find();
foreach ($makeArray['Model'] as $model) {
    $modelList[] = $model['title'];
}
$this->set('models', $models)

Existe alguma maneira mais fácil de obter essa lista sem forçar o make Matriz. Será uma tarefa comum a desenvolve tais cenários na minha candidatura (s).

Agradecemos antecipadamente por qualquer dica!

Foi útil?

Solução 5

A solução pode ser conseguido com a utilização da operação with na matriz habtm no modelo.

Usando with você pode definir a tabela "meio" como:

$habtm = " ...
  'with' => 'MakeModel',
   ... ";

E internamente, no modelo ou Controller, você pode emitir condições para o método find.

Veja: http: / /www.cricava.com/blogs/index.php?blog=6&title=modelizing_habtm_join_tables_in_cakephp_&more=1&c=1&tb=1&pb=1

Outras dicas

Aqui está a minha dica: Tente obter sua consulta escrito em SQL normal antes de tentar reconstruir usando a biblioteca bolo. Em essência, você está fazendo um monte de trabalho extra que a DB pode fazer por você. Sua abordagem (apenas para mostrar - não é bom SQL):

SELECT * FROM makes, models, products WHERE make_id = 5

Você não está levando em consideração as relações (a menos bolo entende auto-magicamente as relações das tabelas)

Você provavelmente está procurando por algo que une essas coisas juntas:

SELECT models.title FROM models 
INNER JOIN products 
  ON products.model_id = models.model_id 
  AND products.make_id = 5

Esperamos que este é um empurrão na direção certa?

A julgar pelo seu comentário, o que você está pedindo é como obter resultados de um determinado modelo, onde a condição é em um modelo relacionado HABTM. Ou seja, algo que você normalmente faria com um JOIN em SQL cru.
Atualmente é um dos poucos pontos fracos do bolo. Existem diferentes estratégias para lidar com isso.

  • Ter o modelo relacionado B devolver todos os ids de possíveis candidatos para o Modelo A, em seguida, fazer uma segunda consulta no Modelo A. ou seja:.

    $this->ModelB->find('first', array('conditions' => array('field' => $condition)));
    array(
        ['ModelB'] => array( ... ),
        ['ModelA'] => array(
            [0] => array(
                'id' => 1
            )
    )
    

    Agora você tem uma matriz de todos ids de ModelA que pertencem a ModelB que corresponda às suas condições, que você pode facilmente extrair usando Set :: extract (). Basicamente, o equivalente de SELECT model_a.id FROM model_b JOIN model_a WHERE model_b.field = xxx. Em seguida, você procurar ModelA:

     $this->ModelA->find('all', array('conditions' => array('id' => $model_a_ids)));
    

    Isso SELECT model_a.* FROM model_a WHERE id IN (1, 2, 3) irá produzir, que é uma forma indireta de fazer o JOIN. Se você precisa de condições em mais de um modelo relacionado, repita até que você tenha todos os ids para ModelA, SQL usará a intersecção de todos os ids (WHERE id IN (1, 2, 3) AND id IN (3, 4, 5)).

  • Se você só precisa de uma condição em ModelB mas deseja recuperar ModelA, basta procurar por ModelB. Bolo irá recuperar automaticamente ModelAs relacionados para você (veja acima). Você pode precisar Set :: extract () novamente, mas isso já pode ser suficiente.

  • Você pode usar o método acima e combiná-lo com a comportamento Containable para obter mais controle sobre os resultados.

  • Se tudo mais falhar ou os métodos acima simplesmente produzir muito em cima, você ainda pode escrever seu próprio SQL crua com $this->Model->query(). Se você ficar com as normas bolo SQL (nomear tabelas corretamente com FROM model_as AS ModelA) Bolo vai ainda pós-processar os resultados corretamente.

Espero que isso envia-lo na direção certa.

chamadas

Toda a sua diferente make> find () e Model-> find () são completamente independentes um do outro. Mesmo make> Model-> find () é o mesmo que Model-> find (), o bolo não de qualquer maneira lembrar ou ter em conta o que já encontradas em outros modelos. O que você está procurando algo como:

$this->Product->find('all', array('conditions' => array('make_id' => 5)));

Confira o método Set :: extract () para obter uma lista de títulos modelo a partir dos resultados de $ this-> make> find ()

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top