2

I am trying to use CakePHP 1.3.5's searchable behavior with containable behavior to return search results for a specified model and an associated model (Article belongsTo User).

Ignoring the searchable behavior for a moment, the following call to find():

$this->Article->find('all', array(
    'conditions' => array('Article.is_published' => 1),
    'fields' => array('Article.id'),
    'contain' => array('User.name')
));

Executes this SQL query:

SELECT `Article`.`id`, `User`.`name`, `User`.`id` FROM `articles` AS `Article` LEFT JOIN `users` AS `User` ON (`Article`.`user_id` = `User`.`id`) WHERE `Article`.`is_published` = 1 

And returns the following array:

Array (
    [0] => Array (
        [Article] => Array (
            [id] => 10
        )
        [User] => Array (
            [name] => Author Name
            [id] => 7
        )
    )
    ...
)

Which is exactly what's expected. However, the following call to search():

$this->Article->search($query, array(
    'conditions' => array('Article.is_published' => 1),
    'fields' => array('Article.id'),
    'contain' => array('Article' => array('User.name'))
));

Executes this SQL query:

SELECT `Article`.`id` FROM `search_index` AS `SearchIndex` LEFT JOIN `articles` AS `Article` ON (`SearchIndex`.`model` = 'Article' AND `SearchIndex`.`association_key` = `Article`.`id`) WHERE `Article`.`is_published` = 1 AND MATCH(`SearchIndex`.`data`) AGAINST('search term' IN BOOLEAN MODE) AND `Article`.`id` IS NOT NULL 

And returns this array:

Array (
    [0] => Array (
        [Article] => Array (
            [id] => 9
        )
    )
    ...
)

Looking at the search() method, it is returning $this->SearchIndex->find('all', $findOptions);. $findOptions contains the following:

Array (
    [conditions] => Array (
        [Article.is_published] => 1
        [0] => MATCH(SearchIndex.data) AGAINST('search term' IN BOOLEAN MODE)
    )
    [fields] => Array (
        [0] => Article.id
    )
    [contain] => Array (
        [Article] => Array (
            [0] => User.name
        )
    )
)

The association isn't getting lost along the way, because inside SearchableBehavior, $this->SearchIndex->Article->belongsTo['User'] is present and intact immediately before and after the call to find() inside the search() method.

The call to search() returns the exact same thing for all of the following values of 'contain':

array('Article' => array('User.name'))

array('Article' => array('User'))

array('Article' => array('User' => array()))

array('Article' => array('User' => array('fields' => array('User.name'))))

array('Article' => array('User' => array('fields' => array('name'))))

Am I doing something wrong? I think I'm using the same format as is instructed in the CakePHP documentation, and I haven't found anything online that suggests that you have to do something special to get search results with associated data.

I know that I could easily achieve the result that I want by just looking up the Users with additional calls to find(), but I'd like to get containable behavior to work like it's supposed to and cut down on unnecessary extra database queries.

Phantom Watson
  • 2,667
  • 4
  • 25
  • 39
  • Thanks for the link! I didn't know it existed a search behavior. I'll be checking it later, is it useful? – metrobalderas Dec 10 '10 at 16:36
  • Supposedly. It does fulltext searches and is customizable in how it indexes your data, but I'm obviously having this problem getting it to return associated model data. – Phantom Watson Dec 10 '10 at 17:02

1 Answers1

1

When using containable, set the recursive option to "true"

$this->Model->Behaviors->attach("Containable",array("recursive"=>true));
John
  • 912
  • 6
  • 12
  • Putting `$this->Article->Behaviors->attach("Containable", array("recursive" => true));` before the call to search() did not change the output. – Phantom Watson Dec 10 '10 at 16:57
  • You need to continue nesting the the models you want to recursively be output – John Dec 17 '10 at 19:06