0

I have models: Project=>Keyword

using HMBTM relationship (set in both models).

The keywords table acts as a Tree, ie. the keywords have hierarchical relationship amongst themselves.

I am using containable behavior.

A user selects a keyword.

I want the returned records (Projects) to be limited by the selected keyword, OR any of that keyword's children. I am trying to reuse my index action.. if no keyword is selected then render the standard index view, if keyword is selected, then find all child keywords and then filter returned projects to those with any of the keyword ids.

I have tried creating an array of children (and original) keyword ids, but I can't work out how to get that array to become the filtering in my find action.

I have tried using :

$this->Project->find('all',
    array(
        'contain' => array('Keyword.id'=>array($childkeywords))     
    )
);

where $childkeywords is an array of the relevant ids, created using array_push. But that does not use key-value pairs, just int values for each id. So I think it is not structured properly.

I feel I want to do something quite easy, but sense I am getting further away from the solution. Is there not a standard way to limit the records to a collection of ids of an associated model?

Cheers

With help from Paulo, I now have:

$this->Project->find('all', array(
                                    'fields' => array('id','title','country', 'project_ref'),
                                    'type' => array('inner'),
                                    'contain' => array('Keyword' => array(
                                                                'conditions' => array('Keyword.id' => $childkeywords)                                               
                                                                            )
                                                    )
                                            )
                                )

But the use of type inner is not changing the results..

Paul Snell
  • 33
  • 2
  • 8

2 Answers2

0

You should have something like this:

$this->Project->find('all', array(
    'contain' => array('Keyword' => array(
                'conditions' => array('Keyword.id' => $childkeywords)
            )
    )
));
Paulo Rodrigues
  • 5,273
  • 7
  • 35
  • 58
  • Paulo, thanks this really helps.. my code has stopped crashing now, but when I debug the created array, it shows ALL the projects and the ones that match the search ids show the associated keyword. What I need is to get rid of the projects that do not have any associated, matching keywords. This feels really close though! It feels like a left outer versus and inner join issue - not sure how to tackle that. – Paul Snell Oct 09 '12 at 14:16
  • I have tried adding the 'type'=>array('inner') to the list of params, but that has not made a difference. – Paul Snell Oct 09 '12 at 14:25
  • Yes, you can add `'type' => 'inner'` but should add in `$belongsTo` array on your `Keyword` model. Have you tried it? – Paulo Rodrigues Oct 09 '12 at 14:51
  • 1
    I have had to use an ugly check on each row to see if the keyword array is empty, and if so, then don't render the row. This seems rather ugly. If anyone knows a better solution, I would love to know. – Paul Snell Oct 09 '12 at 15:36
0

Try something like this:

$this->Project->Keyword->find('all', array(
    'conditions' => array(
        'Keyword.id' => array(1, 2, 3, 4)
    )
));

You do not need to use Containable in this case.

Or you can try TreeBehavior.

bancer
  • 7,475
  • 7
  • 39
  • 58
  • Hi Bancer This solution seems to return a row for every keyword, used or not, and if there is an associated project, then the detail is present.. again, not quite what I was hoping for. I have tree behaviour for the keywords set up. Not sure how it might be used in the context of this problem.. – Paul Snell Oct 09 '12 at 14:55
  • You can set `recursive` to `0` or `-1` to limit the retrieving of the associated records. Replace `1, 2, 3, 4` with Keyword ids you need to retrieve. – bancer Oct 10 '12 at 10:28