How to cleanup/remove the (tag:) from url

Hi guys,

Is it possible to rewrite the tag url.

This : projects/tag:editorial
To: projects/editorial

I have tried all possible ways I think, all from the htaccess to kirbys own routing system, but with no luck.

Best regards /

Fred

As far as I can see, you are hoping to create a route whereby projects/editorial behaves like projects/tag:editorial?

Normal caveat: untested, blah, blah, blah. Give this a go:

c::set('routes', array(
    array(
        'pattern' => 'projects/(:any)',
        'action'  => function($tag) {
            $data = array('tag' => $tag);
            // If page actually exists then return it
            $page = page('projects/' . $tag);
            if($page) return site()->visit($page->uri());
            // Otherwise probably a tag
            return array('projects', $data);
        }
    )
));

The documentation suggests this should work. However, the documentation also suggests that site()->visit($page); should work and it’s not obvious from the source that this is correct. You should end up with a $tag variable being sent to your projects template.

1 Like

Thanks @walkerbox this help me!!!

c::set('routes', array(
  array(
    'pattern' => 'projects/(:any)',
    'action'  => function($tag) {

      // make sure that the projects page is 
      // being set as the currently active page
      site()->visit('projects');

      // send the tag to the template
      return array('projects', array(
        'tag' => $tag        
      ));

    }
  )
));

Good point re site()->visit('projects'). However, wouldn’t subpages fail to be presented properly with this solution?

Ups, I completely misread your code to be honest. Of course your example is totally better when you actually have subpages for projects. Sorry!

BTW: you can use github style syntax highlighting for code blocks, by simple writing:

```php
your code block

at beginning of the code block.

OK - that is cool! Do I still need to indent for that?

If you use Github style code blocks you don’t need to indent at all: https://help.github.com/articles/github-flavored-markdown/#syntax-highlighting

1 Like

Big thanks guys, I really mean it !!

I hope I can contribute and give some back someday.

/ Fred

Ok giving back… ; )

site/config:

c::set('routes', array(
    array(
        'pattern' => '(:all)/(:any)',
        'action'  => function($target, $tag) {
            
            $data = array('tag' => $tag);
            $page = page($target .'/'. $tag);
            $targetPage = page($target);
            
            if (!$targetPage) {
                go('error');
            } else {
                if($page) {
                    return site()->visit($page->uri());
                } else {
                    return array($target, $data);
                }
            }
        }
    )
));

site/controllers/page.php

    return function ($site, $pages, $page, $data) {
        $children = $page->children()->visible();
        if (isset($data['tag'])) {
          $tagged = urldecode($data['tag']);
          $children = $children->filterBy('tags', $tagged, ',');
          if($children->count() == 0){
             go('error');
          }
        }
        return compact('children', 'tagged');
    }

site/snippets/children.php

<?php $children = $data; ?>

<?php foreach($children as $child): ?>
    <?php echo $child->title() ?>
    <?php if(!$child->tags()->empty()): ?>
        <p>
          <?php foreach($child->tags()->split(',') as $tag): ?>
              <a href="<?php echo $page->url() .'/'. $tag ?>">
                  <?php echo html($tag) ?>
              </a>
          <?php endforeach ?>
        </p>
    <?php endif ?>
<?php endforeach ?>

site/snippets/tags.php

<?php
$tags = $page->children()->visible()->pluck('tags', ',', true);

if($tags): ?>
<ul class="tags">
  <li><a href="<?php echo $page->url() ?>">All</a></li>
  <?php foreach($tags as $tag): ?>
    <li>
      <a <?php e($tag == $tagged, ' class="active"') ?>  
      href="<?php echo $page->url() . '/' . $tag ?>">
        <?php echo $tag ?>
      </a>
    </li>
  <?php endforeach ?>
</ul>
<?php endif ?>

site/template/page.php

<?php snippet('tags'); ?>
<?php snippet('children', array('data' => $children)); ?>

hmm…
Ended up with a problem of course… ; )

There was a problem redirecting to the error page if no ‘page’ or ‘tag’ exist.
If there was no ‘page’ in config then it was a ‘tag’, but if there was no ‘tag’ i had
a problem…

If you guys have a cleaner/smoother solution to the problem please share…
But I think this works quite well…

/ Fred

In the controller, you could do a filterBy() on all project pages with the tag - and if that collection has a count of 0, send the visitor to the error page, otherwise to the projects page with the tag.

lol thanks @distantnative, I have updated the code…
Knew I had overdone it… ; )

Added a ‘tagcloud’ snippet with active class.

Fixed blank screen of death if no target page exist… (config.php).

Quick question - I’m using the below:

c::set('routes', array(
  array(
    'pattern' => array('topics/(:all)'),
    'action'  => function($tag) {
		site()->visit('topics');

      // send the tag to the template
      return array('topics', array(
        'tag' => $tag        
      ));
    }
  )
));

Then in my template I have:

if (isset($data['tag'])) {
	echo $data['tag'];
}

Visiting a sample URL, eg:

http://site.dev/topics/test

gives me no result, but should echo “test”, correct? Any ideas?

Thank you!

I think you have to use a controller to get the additional arguments:

topics.php controller

<?php

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

 if (isset($args['tag'])) {
	$tag = $args['tag'];
 }
 
 // then do some filtering by tag here

 return compact('args');

};
```

In your template

```
<?php
var_dump($args);
```

Awesome - this works. Thank you!

One follow-up question – does this input need to be sanitized or is that already handled internally in Kirby?

Thanks again!

Kirby does not automatically sanitize input, so you would have to take care of that yourself. If that is necessary or not depends on what you want to do with the input, if you just want to filter pages, that would not be necessary as a wrong input string would just not return anything. For other use cases, e.g. when calling input as a page method, you would have to make sure that only allowed strings can be used.

1 Like