3

I have some child pages that have categories associated with them. For categories that have more than 1 word e.g "Test Category" I need the output to be 1 word with the spaces separated by dashes e.g "Test-Category"

How can the function be rewritten to handle this?

public function CategoriesList() {
    if ($this->Categories()->exists()) {
        return implode(', ', $this->Categories()->column('Title'));
    }
}
scrowler
  • 24,273
  • 9
  • 60
  • 92
KenSander
  • 113
  • 7

4 Answers4

6

We can create a getDashedTitle function in our Category class to return a title with dashes instead of spaces:

class Category extends DataObject {
    public function getDashedTitle() {
        return str_replace(' ', '-', $this->Title);
    }
}

We can then use DashedTitle in the map function to fetch the category dashed titles:

public function CategoriesList() {
    if ($this->Categories()->exists()) {
        return implode(', ', $this->Categories()->map('ID', 'DashedTitle')->toArray());
    }
}
3dgoo
  • 15,716
  • 6
  • 46
  • 58
3

You can use an Extension for this. This means that this method will be available for any varchar field.

mysite/code/extensions/VarcharDecorator.php

<?php
class VarcharDecorator extends Extension {
    function Slugify() {
        return FileNameFilter::create()->filter(trim($this->owner->value);
    }
}

mysite/_config/extensions.yml

Varchar:
  extensions:
    - VarcharDecorator

Now you can use $Title.Slugify in your templates.

<% loop $Categories %>
  $Title.Slugify<% if not $Last %>, <% end_if %>
<% end_loop %>
Gavin Bruce
  • 1,799
  • 16
  • 28
2

This is untested, but assuming Categories() returns a HasManyList you could try something like this:

public function CategoriesList()
{
    if (!$this->Categories()->exists()) {
        return '';
    }

    $output = [];
    foreach ($this->Categories() as $category) {
         $output[] = implode('-', explode(' ', $category->Title()));
    }

    return implode(', ', $output);
}

This will break the title up by spaces then put it back together with dashes, finally joining all Titles together with , and returning that.

scrowler
  • 24,273
  • 9
  • 60
  • 92
2

The FileNameFilter class will do what you need out of the box:

FileNameFilter::create()->filter("Test Category 1")

For more flexibility or custom functionality, you could extend the class and overload the filter function:

class CategoriesFilter extends FileNameFilter {

  public function filter($name) {
    //do your processing on $name
    return $name;
  }

}
scrowler
  • 24,273
  • 9
  • 60
  • 92
cryptopay
  • 1,084
  • 6
  • 7