# How to use \`str::slug\`

**URL:** <https://forum.getkirby.com/t/how-to-use-str-slug/5301>\
**Category:** Questions\
**Tags:** v2\
**Created:** [September 20, 2016, 10:01pm UTC](https://forum.getkirby.com/t/how-to-use-str-slug/5301 "2016-09-20T22:01:51Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![afincato](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/afincato/32/3446_2.png) [@afincato](https://forum.getkirby.com/u/afincato)\
**Post date:** [September 20, 2016, 10:01pm UTC](https://forum.getkirby.com/t/how-to-use-str-slug/5301/1 "2016-09-20T22:01:51Z")

</div>

Looking at the toolkit API I found the `str::slug` function.

I tried to read [this topic](https://forum.getkirby.com/t/append-field-content-in-another-field/4044/15) to get a sense of how to use the function, but it seems overkill for what I need.

I just need to `split` and `slug` a `foreach` containing tags. How could I do that?

PS. maybe only useful for noobs, but if in the API page there would be an example for each method, it would make learning kirby **and** `PHP` much easier I think!

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [September 20, 2016, 10:29pm UTC](https://forum.getkirby.com/t/how-to-use-str-slug/5301/2 "2016-09-20T22:29:39Z")

</div>

This is the function:

```auto
/**
   * Convert a string to a safe version to be used in a URL
   *
   * @param string $string The unsafe string
   * @param string $separator To be used instead of space and other non-word characters.
   * @return string The safe string
   */
  public static function slug($string, $separator = null, $allowed = null) {

    $separator = $separator ?: static::$defaults['slug']['separator'];
    $allowed = $allowed ?: static::$defaults['slug']['allowed'];

    $string = trim($string);
    $string = static::lower($string);
    $string = static::ascii($string);

    // replace spaces with simple dashes
    $string = preg_replace('![^' . $allowed . ']!i', $separator, $string);
    // remove double dashes
    $string = preg_replace('![' . preg_quote($separator) . ']{2,}!', $separator, $string);
    // trim trailing and leading dashes
    $string = trim($string, $separator);
    // replace slashes with dashes
    $string = str_replace('/', $separator, $string);

    return $string;

  }

```

(/kirby/toolkit/lib/str.php)

I hope the comments are self-explanatory, if not, please don’t hesitate to ask.

An example:

```auto
<?= str::slug(' Das ist aber eine Überraschung!!!') ?>

```

Will result in:

```auto
das-ist-aber-eine-ueberraschung

```

But you are right, some documentation would be great.

Not sure if that’s what you are after, but to loop through list of comma separated tags, you can do this:

```auto
<ul>
<?php
$tags = $page->tags()->split();
foreach($tags as $tag): ?>
  <li><?= $tag ?></li>
<?php endforeach ?>
</ul>

```

---

<div class="post-metadata">

**Author:** ![afincato](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/afincato/32/3446_2.png) [@afincato](https://forum.getkirby.com/u/afincato)\
**Post date:** [September 28, 2016, 12:10pm UTC](https://forum.getkirby.com/t/how-to-use-str-slug/5301/3 "2016-09-28T12:10:26Z")

</div>

(Sorry)  
I had time to try this out only today.

I am trying to `sluggify` a `foreach` loop outputting tags.

I tried to simplify and adjust the code from [this post](https://forum.getkirby.com/t/append-field-content-in-another-field/4044/15) to my needs, but it’s not working.

In `blog.php`'s controller I have:

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

  // get all articles
  $articles = $page->children()->visible()->flip();

  // fetch all tags
  $topics = $articles->pluck('topics', ',', false);

  //add tag filter (`topic`)
  if(!empty(param('topics'))) {
    $topics = str::slug(param('topics'));
    $articles = $articles->filter(function($article) use($topics) {
      // split tags and convert to lowercase
      $topics = array_map('str::slug', $article->topics()->split(','));
    });
  }
  return compact('articles', 'topics', 'topic');

};

```

and in the `blog.php` template:

```auto
<?php foreach($topics as $topic): ?>
  <div class="c-tag-collection__tag-name filter" data-filter=".<?php echo html($topic) ?>">
	<?php echo html($topic) ?>
  </div>
<?php endforeach ?>

```

Is it better to add `slug::` in the controller or directly in the template?  
What am I doing wrong?

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [September 28, 2016, 12:35pm UTC](https://forum.getkirby.com/t/how-to-use-str-slug/5301/4 "2016-09-28T12:35:49Z")

</div>

Your filter does not return anything, try this:

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

  // get all articles
  $articles = $page->children()->visible()->flip();

  // fetch all tags
  $topics = $articles->pluck('topics', ',', false);

  //add tag filter (`topic`)
  if(!empty(param('topics'))) {
    $filter = str::slug(param('topics'));
    $articles = $articles->filter(function($article) use($topics) {
      // split tags and convert to lowercase
      $topics = array_map('str::slug', $article->topics()->split(','));
      // return the page if the filter is in the array
      if(in_array($filter, $topics)) return true;
    });
  }
return compact('articles', 'topics');

};

```

---

<div class="post-metadata">

**Author:** ![afincato](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/afincato/32/3446_2.png) [@afincato](https://forum.getkirby.com/u/afincato)\
**Post date:** [September 28, 2016, 12:50pm UTC](https://forum.getkirby.com/t/how-to-use-str-slug/5301/5 "2016-09-28T12:50:13Z")

</div>

Updated, but it still output tags with spaces when there is a multi-word tag with a space.

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [September 28, 2016, 12:57pm UTC](https://forum.getkirby.com/t/how-to-use-str-slug/5301/6 "2016-09-28T12:57:45Z")

</div>

You would have to str::slug your topics in the template as well, or array\_map them in the controller:

controller

```auto
$topics = array_map('str::slug', $articles->pluck('topics', ',', false));

```

or

```auto
<?php foreach($topics as $topic): ?>
  <div class="c-tag-collection__tag-name filter" data-filter=".<?php echo str::slug($topic) ?>">
	<?php echo str::slug($topic)) ?>
  </div>
<?php endforeach ?>

```

---

<div class="post-metadata">

**Author:** ![afincato](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/afincato/32/3446_2.png) [@afincato](https://forum.getkirby.com/u/afincato)\
**Post date:** [September 28, 2016, 1:55pm UTC](https://forum.getkirby.com/t/how-to-use-str-slug/5301/7 "2016-09-28T13:55:17Z")

</div>

Great!

Last thing, is there a way to combine the `implode` function with the `slug` one?

What I’d like to accomplish would be something like:

```auto
<div class="blog-entry__element flex mix tag-1 tag-word-word tag-etc">

```

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [September 28, 2016, 2:19pm UTC](https://forum.getkirby.com/t/how-to-use-str-slug/5301/8 "2016-09-28T14:19:23Z")

</div>

This could work:

```auto
$topics = implode(' ', array_map('str::slug', $article->topics()->split(',')));

```

---

<div class="post-metadata">

**Author:** ![afincato](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/afincato/32/3446_2.png) [@afincato](https://forum.getkirby.com/u/afincato)\
**Post date:** [September 28, 2016, 2:30pm UTC](https://forum.getkirby.com/t/how-to-use-str-slug/5301/9 "2016-09-28T14:30:52Z")

</div>

Amazing! It works, thank you 🎉

---

<div class="post-metadata">

**Author:** ![distantnative](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/distantnative/32/11319_2.png) [@distantnative](https://forum.getkirby.com/u/distantnative)\
**Post date:** [February 6, 2025, 4:55pm UTC](https://forum.getkirby.com/t/how-to-use-str-slug/5301/10 "2025-02-06T16:55:09Z")

</div>

Archived on February 6, 2025, 4:55pm UTC


