2010-11-29 56 views
0

Ce que j'ai:maîtrisable ne filtre pas le modèle de niveau 2 avec HABTM et hasMany

"A" HABTM "C" HABTM "A" through join table "B" 
"A" hasMany "B" belongsTo "A" 
"C" is ordered by a "B" field 

Ce que je veux:

// result: 
[0] => array( 
    A => array(/* single model's fields I still need*/), 
    C => array(
     [0] => array(C.field1, C.field2, ... /* Model C fields*/), 
     [1] => array(C.field1, C.field2, ...) 
    ) 
) 

Ce que j'ai essayé:

// this gives me data I don't need: 
A->find('all', array('conditions' => array('id' => $id))) 
// result: 
[0] => array( 
    A => array(/* single model's fields I need*/), 
    B => array(/* I DON'T NEED */ 
     [0] => array(...) 
     [1] => array(/* ... etc, tons records I don't need */) 
    ), 
    C => array(
     [0] => array(C.field1, C.field2, ... /* I need these fields*/ 
      [B] => array(/* I DON'T NEED */) 
     ), 
     [1] => array(C.field1, C.field2, ... ) 
      [B] => array(/* ... etc, each has a model B I don't need ... */) 
     ) 
    ) 
) 

En utilisant maîtrisable, je peux réduire la requête un peu, mais il y a modèle encore associé cruft:

// this is a little better 
A->find('all', array( 
    'conditions' => array('id' => $id), 
    'contain' => array('C') 
)) 
// result: 
[0] => array( 
    A => array(/* single model's fields I still need*/), 
    C => array(
     [0] => array(C.field1, C.field2, ... /* I still need Model C fields*/ 
      [B] => array(/* I still DON'T need this Model's fields */) 
     ), 
     [1] => array(C.field1, C.field2, ... 
      [B] => array(/* ... still has unneeded model B */) 
     ) 
    ) 
) 

NB1: Je l'ai lu this, this et this du livre, ainsi que this et this.

NB2: J'ai aussi essayé

C->recursive = -1 // no effect 

C->unbindModel(array('hasAndBelongsToMany'=>A)) // no effect 

A->find('all', array(     // not what I want, but it's still 
    'conditions' => array('id' => $id), // odd that this doesn't filter C's 
    'contain' => array('A.B')));   // fields out. same as second result 

A->find('all', array(     // also not what I want, but it's 
    'conditions' => array('id' => $id), // weird that this doesn't filter B's 
    'contain' => array('A.B.field'))); // fields at all; 

Répondre

1

Le ContainableBehavior renverra automatiquement les champs nécessaires à la carte des résultats.

Je cite un page que vous avez déjà lu:

$this->Post->find('all', array('contain' => 'Comment.author')); 

... // data returned: 

[Comment] => Array 
    (
     [0] => Array 
      (
       [author] => Daniel 
       [post_id] => 1 
      ) 
... 

Comme vous pouvez le voir, les tableaux de commentaires contiennent seulement le champ auteur (plus post_id qui est nécessaire par CakePHP pour cartographier la résultats).

Dans le cas des relations HABTM, la jointure modèle avec les clés étrangères associées est retournée, puisque les a_id et c_id champs sont exigés par maîtrisable. Ma suggestion est juste de l'ignorer et de prendre les valeurs dont vous avez besoin. Si vous le souhaitez, vous pouvez probablement jeter un oeil à joins car Containable interroge parfois le DB plusieurs fois. Cependant, les données pour les modèles associés ne seront pas retournées aussi bien que Containable.

+0

Pour ceux d'entre vous qui cherchent la même chose, j'ai fini par formater le tableau avec $ A = $ data ['A']; $ B = Set :: classicExtract ($ data, 'B. {n}. {Champ1 | champ2 | champ3 | champ4}'); $ data = array ( 'A' => $ A, 'B' => $ B ); –