Filtering Page List by Multiple Tags

Permalink
I know it is not strictly the way it was intended to work but I am trying to filter a page list by multiple tags. I am currently working on a site (running 5.5.2.1 currently) which lists locations with differing facilities available. These are all set up as pages with a tags custom attribute. Rather than a blog style "pages related by a specific tag" setup I am trying to set up tags as facilities on offer so that a search can look for more than one tag at a time e.g. Locations which are open to the public AND have disabled access.

I have hard coded a form to includes a tag list with a custom template to output selection boxes. This posts an array of selected tags to the filtered list:

<?php foreach($options as $opt) { ?>
<label for="<?php echo $opt ?>" class="checkbox inline">
  <input type="checkbox" id="<?php echo $opt ?>" name="tags[]" value="<?php echo $opt ?>"> <?php echo $opt ?></label>


I have managed to get the page list set up and working filtering on a single tag using:

$tags = implode(", ", $_POST['tags']);
$pl->filterByAttribute('tags', "%\n{$tags}\n%", "like");


however when multiple tags are selected 0 pages are returned when I know there are multiple pages matching the criteria.

Is there a way to compare the posted array with each locations tags attribute array using the $pl->filterByAttribute setup or is there a better way to accomplish this?

Any advice or pointers gratefully received.

Thanks
Paul

View Replies: View Best Answer
Remo replied on at Permalink Best Answer Reply
Remo
The tags are separated with \n in the database.

You could search for \ntagA\ntagB\n but the order of the tags is not guaranteed.

Have a look at this code:
<?php
Loader::model('page_list');
$pl = new Pagelist();
$pl->debug();
$tags = array('a','b');
foreach ($tags as $tag) {
    $pl->filterByAttribute('test_tags', "%\n{$tag}\n%", "like");
}
$pages = $pl->getPage();
foreach ($pages as $page) {
    echo $page->getCollectionName() . '<br>';
}


It adds a filter per tag. I've also added $pl->debug(); which helps you a lot to track down the problem. If added before getPage, it will print the SQL query used to filter the pages.
phowie74 replied on at Permalink Reply
Thanks Remo - I just got your email as I posted my own reply!

Much appreciated and certainly some useful info for futre reference with the $pl->debug();

Many Thanks
Paul
phowie74 replied on at Permalink Reply
I think I have answered my own question! Just in case anybody else has a similar query here is my solution.

I took a look at the /concrete/blocks/search/controller.php as that allows for an array of multiple tags and found this snippet lurking:

if (is_array($_REQUEST['akID'])) {
  Loader::model('attribute/categories/collection');
  foreach($_REQUEST['akID'] as $akID => $req) {
    $fak = CollectionAttributeKey::getByID($akID);
    if (is_object($fak)) {
      $type = $fak->getAttributeType();
      $cnt = $type->getController();
      $cnt->setAttributeKey($fak);
      $cnt->searchForm($ipl);
      $aksearch = true;
    }
  }
}


Which I have tailored to loop through each tag filtering tags in turn:
if (is_array($_POST['tags'])) {
  foreach($_POST['tags'] as $tags => $tag) {
    $pl->filterByAttribute('tags', "%\n{$tag}\n%", "like");
  }
}


Much simpler than I had been making it I guess.

Thanks
Paul