Filtering multiple tags

I’m not quite sure what exactly you want to achieve. The following controller will work if you want to filter only by one type of parameter at a time:

<?php

	return function($site, $pages, $page) {

	    $projects = page('projects')
	                        ->children()
	                        ->visible();
	                 

		
		if($color = param('color')) {
			$projects =  page('some-page')
		                        ->children()
		                        ->visible()
		                       ->filterBy('colors', $color, ',');

		}
		if($client = param('client')) {
			$projects =  page('some-page')
		                        ->children()
		                        ->visible()
		                       ->filterBy('clients', $client, ',');

		}
		if($service = param('service')) {
			$projects =  page('some-page')
		                        ->children()
		                        ->visible()
		                       ->filterBy('services', $service, ',');
		}                       
		 
		  return compact('projects');

	};

This piece if code assumes that you have 3 type of tag fields in your blueprints:

  • colors
  • services
  • clients

And you want to filter either by color OR by client OR by service.

That is, if you enter a URL like this:

http://yourdomain.com/some-page/color:green

you get a list of children with color green.

But chaining parameters will not work with this code.

1 Like

Yes, I understand how that works. Thank you. However, I’m having trouble piecing together something similar for the following example:

<?php if(param('tag')): // show projectname results ?>
    <?php $tag = urldecode(param('tag'));
          $articles = $pages->find('home')
                            ->children()
                            ->visible()
                            ->filterBy('tags', $tag, ',');

          echo '<h1 class="title">' , $tag , '</h1>';?>

Of course I have the code : <?php else: // show latest articles ?> later

This works for one type of parameter. I want to extend this to work with multiple filters. How can I achieve the same result if I click on the “color” tag, the “client” tag, or “service” tag - individually?

Hm, I’m not quite sure where the problem is and how I could best help to solve it. You code above does not really make sense.

What I posted above is the code for a controller which return the $projects variable, that you can then use to iterate through the projects in your template.

@texnixe that’s right, I understand the controller. How you layer in tags under one request is what I’m trying to learn and extend. For example, with Baseblog (re: http://baseblog.sashtown.de/demo/) clicking on a tag ($tag) will bring you to a page showing the title of the active $tag. I want to do something similar using multiple custom tag fields. So, whether I click on client, service, projects, color …etc, I will see the title on the page change to Client, Service, Projects, etc. depending on which tag was selected.

The following code is from Baseblog’s ‘blog’ template:

<?php if(param('tag')): // show tag results ?>
    <?php $tag = urldecode(param('tag'));
          $articles = $pages->find('blog')
                            ->children()
                            ->visible()
                            ->filterBy('tags', $tag, ',')
                            ->flip()
                            ->paginate(10);

          echo '<h1 class="result">Articles tagged with “<mark>' , $tag , '</mark>”</h1>';
    ?>

Is there a way I can extend the above code to include more than one tag?
Thank you!
Shannon

For a working example of how I’d like to use the above example see: http://ssssssss.info/mmp/

I see. You could simply use a new variable in your controller. In each if-statement, add something like:


$title = $tag;

and in the others then set $title to color, service etc, and return the variable.

Then you can echo that variable as headline in your template.

I tried something different and included the following code in the controller for each if statement:
echo '<h1 class="result"> Articles tagged with “<mark>' , $tag , '</mark>”</h1>';
replacing $tag with color, service, etc.

This will display the title of the active tag but in markup it sits above my ‘head’ elements in the body. Yucky.

I understand why this is happening and yet I don’t know how to approach your, @texnixe, solution in my template. This is challenging!

Thanks,
Shannon

As I wrote above, save the tag in a variable that you return in your controller:

<?php
if(param('tag')) {
  $tag = urldecode(param('tag'));
          $articles = $pages->find('home')
                            ->children()
                            ->visible()
                            ->filterBy('tags', $tag, ',')

  $title = $tag;
}
if(param('color') {
  $color = urldecode(param('color'));
          $articles = $pages->find('home')
                            ->children()
                            ->visible()
                            ->filterBy('colors', $color, ',')

  $title = $color;
}
...
else {
  //show all articles
}

    return compact('articles', 'title'); 
    ?>

Then in your template:

<h1 class="title">Articles tagged with <mark><?php echo  $title ?></mark></h1>

You should not put any html into your controller, it’s just for the logic and should return something, not echo anything.

As aways, thank you for your patience and assistance @texnixe.

If you want get something only with tags “tag1” and “tag2”, like a yoururl.com/page/tag:tag1,tag2 you’re can use this code, (change $products whatever you want) :

if(param('tag')){
    $tags = explode(",", param('tag'));
    $products = $products->filter(function($product) use ($tags) {
      $inTags = true;
      foreach ($tags as $tag) {
        $pTags = explode(",", $product->tags()); //get tags field from page
        if(!in_array($tag,$pTags)){
          $inTags = false;
        }
      }
      return $inTags;
    });
  }
2 Likes