Note that there are some explanatory texts on larger screens.

plurals
  1. POCakeDC Search and Tag plugin - search for multiple tags
    primarykey
    data
    text
    <p>Hopefully I'm missing something simple here. I'm using the CakeDC Search and Tags plugin for my cake (2.3.4) app. </p> <p>Along with generic search by field functionality I want the user to be able to search by tags. I've almost got this working but the search will only display results if you search for a single tag not multiples. For example, if I add an article with the following tags - black, white, red. The article will only show in the search results if I search for a single tag (say, black) and not all 3, or even 2... What am I missing?</p> <p>Heres my code:</p> <p>Article.php model</p> <pre><code>class Article extends AppModel { public $actsAs = array( 'Upload.Upload' =&gt; array( 'screenshot1' =&gt; array ( 'fields' =&gt; array ( 'dir' =&gt; 'dir' ), 'thumbnailMethod' =&gt; 'php', 'thumbnailSizes' =&gt; array( 'xvga' =&gt; '1024x768', 'vga' =&gt; '640x480', 'thumb' =&gt; '80x80' ), ), ), 'Search.Searchable', 'Tags.Taggable' ); // Search plugin filters public $filterArgs = array( 'title' =&gt; array('type' =&gt; 'like'), 'environment' =&gt; array('type' =&gt; 'like'), 'description' =&gt; array('type' =&gt; 'like'), 'error' =&gt; array('type' =&gt; 'like'), 'cause' =&gt; array('type' =&gt; 'like'), 'resolution' =&gt; array('type' =&gt; 'like'), 'live' =&gt; array('type' =&gt; 'value'), 'synced' =&gt; array('type' =&gt; 'value'), 'tags' =&gt; array('type' =&gt; 'subquery', 'method' =&gt; 'findByTags', 'field' =&gt; 'Article.id'), array('name' =&gt; 'search', 'type' =&gt; 'query', 'method' =&gt; 'filterQuery'), ); // This is the OR query that runs when the user uses the client side signle field search public function filterQuery($data = array()) { if(empty($data['search'])) { // search is the name of my search field return array(); } $query = '%'.$data['search'].'%'; return array( 'OR' =&gt; array( 'Article.title LIKE' =&gt; $query, 'Article.description LIKE' =&gt; $query, 'Article.error LIKE' =&gt; $query, ) ); } // Find by tags method public function findByTags($data = array()) { $this-&gt;Tagged-&gt;Behaviors-&gt;attach('Containable', array('autoFields' =&gt; false)); $this-&gt;Tagged-&gt;Behaviors-&gt;attach('Search.Searchable'); $query = $this-&gt;Tagged-&gt;getQuery('all', array( 'conditions' =&gt; array('Tag.name' =&gt; $data['tags']), 'fields' =&gt; array('foreign_key'), 'contain' =&gt; array('Tag') )); return $query; } public $hasAndBelongsToMany = array( 'Category' =&gt; array( 'className' =&gt; 'Category', 'joinTable' =&gt; 'articles_categories', 'foreignKey' =&gt; 'article_id', 'associationForeignKey' =&gt; 'category_id', 'unique' =&gt; 'keepExisting', 'conditions' =&gt; '', 'fields' =&gt; '', 'order' =&gt; '', 'limit' =&gt; '', 'offset' =&gt; '', 'finderQuery' =&gt; '', 'deleteQuery' =&gt; '', 'insertQuery' =&gt; '' ), 'Tag' =&gt; array('with' =&gt; 'Tagged') ); </code></pre> <p>Controller method</p> <pre><code>public function admin_advancedSearch() { // Disable validation for this action $this-&gt;Article-&gt;validate = array(); // For search plugin $this-&gt;Prg-&gt;commonProcess(); // Set searched for details $this-&gt;set('searchedFor', $this-&gt;passedArgs); // If passed args are all empty if ($this-&gt;passedArgs) { if (empty($this-&gt;passedArgs['title']) AND empty($this-&gt;passedArgs['environment']) AND empty($this-&gt;passedArgs['description']) AND empty($this-&gt;passedArgs['error']) AND empty($this-&gt;passedArgs['cause']) AND empty($this-&gt;passedArgs['resolution']) AND empty($this-&gt;passedArgs['live']) AND empty($this-&gt;passedArgs['synced']) AND empty($this-&gt;passedArgs['tags'])) { $this-&gt;Session-&gt;setFlash('Please enter at least one search criteria', 'flash_failure'); // Set this var for checks in view $this-&gt;set('emptySeach', true); } else { $paginateConditions = $this-&gt;Article-&gt;parseCriteria($this-&gt;passedArgs); $this-&gt;paginate = array('conditions' =&gt; array( $paginateConditions), 'limit' =&gt; 10, 'order' =&gt; array('Article.modified' =&gt; 'DESC')); $this-&gt;set('articles', $this-&gt;paginate()); // Count number of results $count = 0; foreach ($this-&gt;paginate() as $result) { $count++; } $this-&gt;set('resultsCount', $count); // Search was not empty - set flag for view $this-&gt;set('emptySeach', false); } } // Set layout $this-&gt;layout = 'admin'; //debug($this-&gt;passedArgs); } </code></pre> <p>All plugins are loaded successfully from bootstrap, searches work fine without tags. Searches with tags only work if one tag is entered....</p> <p>*<em>EDIT *</em> If I debug $query from the findByTags method I get this:</p> <pre><code>'SELECT `Tagged`.`foreign_key` FROM `knowledgebase`.`tagged` AS `Tagged` LEFT JOIN `knowledgebase`.`tags` AS `Tag` ON (`Tagged`.`tag_id` = `Tag`.`id`) WHERE `Tag`.`name` = 'kia, rio, red'' </code></pre> <p>So it looks like its trying to find a single tag with all the searched for tags in its name. How can I make the WHERE part an IN?</p> <p>For example:</p> <pre><code>WHERE `Tag`.`name` IN ('kia', 'rio', 'red') </code></pre> <p>Thanks</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload