Search code examples
phpjoomlafiltertagsjoomla-k2

Filter articles by tag inside a category - Joomla and K2


I would like to make a custom module with a list of tags. When a tag is clicked the visitor would be navigated to a category page that would show articles with that tag.

I am not a joomla expert, I was thinking about a solution like a hyperlink like this that I would add to the tags inside the module:

href="http://mywebsite.com/index.php/itemlist/tag/tokio%20city?category=places"

Is this possible? Or how could I achieve this result? Thanks!


Solution

  • This is a bit more complicated than just a query string in the URL as you also need to tweak a template.

    If you want to keep it as simple as possible, I'd would recommend creating a new K2 template using template overrides and editing the category template so that it would read the query string parameters and show only articles already filtered by the category and furthermore by the tag via a query string.

    That's just a brief how-to, now with a lil bit more details:

    1) Create a new K2 template using template overrides.

    In your template, if it doesn't exist already, create a folder structure /templates/your_template/html/com_k2/templates/default. The "default" can be replaced with any name if you want to have more K2 templates, but you have to set the new template to each category you have manually.

    Now take the content from "/components/com_k2/templates/default" and copy it to the new folder in your template. Now, K2 is using the templates from your /templates/your_template/html/com_k2/ folder. Feel free to google more details if you don't understand template overrides, it's pretty important thing when customizing a template.

    2) Edit your category view file to accommodate the list to your query strings

    The file that interests you now is in /templates/your_template/html/com_k2/templates/default/category.php. Open this file and try to understand what's important there:

    Line 141
    <?php foreach($this->leading as $key=>$item): ?>
    Line 169
    <?php foreach($this->primary as $key=>$item): ?>
    Line 197
    <?php foreach($this->secondary as $key=>$item): ?>
    Line 226
    <?php foreach($this->links as $key=>$item): ?>
    

    This is what matters. In these four foreach loops, there are all the items. Then, you can wrap the content of each of these loops into an if-condition to check whether it has the desired tag that is specified in the URL.

    To show you an example, this is the code for <div id="itemListPrimary">. You can replace this whole div in the category.php file with the following code and it will work flawlessly. I've just written and tested it.

    <div id="itemListPrimary">
    
        <?php foreach ($this->primary as $key=>$item): ?>
    
            <?php
            # Get the value of the "tag" query string
            $jInput = JFactory::getApplication()->input;
            $myTag = $jInput->get('tag', null, 'STRING'); // Joomla 1.6+
            //$myTag = JRequest::getVar('tag'); // for Joomla 1.5
    
            # If the tag is empty, the query string is not specified and we'll go standard way without any tag filter
            if (empty($myTag)) {
    
                // Define a CSS class for the last container on each row
                if ((($key+1)%($this->params->get('num_secondary_columns'))==0) || count($this->secondary)<$this->params->get('num_secondary_columns'))
                    $lastContainer= ' itemContainerLast';
                else
                    $lastContainer='';
                ?>
                <div class="itemContainer<?php echo $lastContainer; ?>"<?php echo (count($this->secondary)==1) ? '' : ' style="width:'.number_format(100/$this->params->get('num_secondary_columns'), 1).'%;"'; ?>>
                    <?php
                        // Load category_item.php by default
                        $this->item=$item;
                        echo $this->loadTemplate('item');
                    ?>
                </div>
                <?php if(($key+1)%($this->params->get('num_secondary_columns'))==0): ?>
                <div class="clr"></div>
                <?php endif;
    
            # Otherwise the tag is set so we'll filter the articles by the tag
            } else {
    
              # Get an array of all the tags that the current article in the loop has
              $articleTags = array();
              foreach ($item->tags as $tag) {
                  $articleTags[] = $tag->name;
              }
    
              # Check if the article has the tag specified in the URL as a query string
              if (in_array($myTag, $articleTags)) {
    
                  # Now the default content of the foreach loop comes as written in the default K2 category.php template
    
                  // Define a CSS class for the last container on each row
                  if ((($key+1)%($this->params->get('num_secondary_columns'))==0) || count($this->secondary)<$this->params->get('num_secondary_columns'))
                      $lastContainer= ' itemContainerLast';
                  else
                      $lastContainer='';
                  ?>
                  <div class="itemContainer<?php echo $lastContainer; ?>"<?php echo (count($this->secondary)==1) ? '' : ' style="width:'.number_format(100/$this->params->get('num_secondary_columns'), 1).'%;"'; ?>>
                      <?php
                          // Load category_item.php by default
                          $this->item=$item;
                          echo $this->loadTemplate('item');
                      ?>
                  </div>
                  <?php if(($key+1)%($this->params->get('num_secondary_columns'))==0): ?>
                  <div class="clr"></div>
                  <?php endif;
              }
            } ?>
    
        <?php endforeach; ?>
    </div>
    

    3) Understand how the URLs will work

    My typical category URL is:

    http://mywebsite.com/category-name
    

    To show only articles with a specified tag, use:

    http://mywebsite.com/category-name?tag=your-tag
    

    For instance, if you want to show only articles with the "Tokio City" tag, use:

    http://mywebsite.com/category-name?tag=Tokio City
    

    Done.

    That's the basics of what you needs. It's all you need if you use primary articles only (no leading and secondary or links). Of course there are plenty more things you might want to take care of:

    • a notice if there is no article with the specified tag
    • no redundant code, I've written it like this for the sake of simplicity and readability
    • SEO - spaces and special characters in URLs
    • making sure no empty div will be printed

    But that would be way more code and I wanted to keep it simple & readable for you. I think I gave you more than enough for a start, so go ahead and get it done, good luck :)