12

What is the best way to convert a string of text to a slug? Meaning:

  • alpha allowed, convert to lowercase
  • numbers are allowed
  • spaces should be eliminated, not converted to dash ("-")
  • accented characters replaced by equivalent standard alpha
  • no other characters allowed, should be stripped out

I have found plenty of code online, but it all tends to convert spaces to dashes, which I do not want to do.

I am also interested optionally in varying the conversion, wherein:

  • ampersand ("&") should be replaced by the string "and"

And also a variant wherein:

  • Don't bother converting accented characters to equivalent standard alpha
5
  • 2
    so youwantyoururltolooklikethis instead of the cleaner looking you-want-your-url-to-look-like-this? Also, accented characters replaced by equivalent standard alpha but Don't bother converting accented characters. Which? Commented Nov 16, 2016 at 21:04
  • 2
    Pick a solution that's close to what you want, then modify it to add your special requirements. Commented Nov 16, 2016 at 21:06
  • You could simply remove all the dashes from the result of a standard slug generator. Commented Nov 16, 2016 at 21:07
  • 2
    There are libraries like github.com/cocur/slugify or github.com/ausi/slug-generator that allow you to customize the character translations and the delimiter. Commented Oct 30, 2017 at 22:17
  • @ausi, that's brilliant. Thanks. Commented Oct 31, 2017 at 8:30

4 Answers 4

28

Here is a modified function that I originally found here (http://cubiq.org/the-perfect-php-clean-url-generator). you can pass '' as the delimiter to not use '-'.

public static function createSlug($str, $delimiter = '-'){

    $slug = strtolower(trim(preg_replace('/[\s-]+/', $delimiter, preg_replace('/[^A-Za-z0-9-]+/', $delimiter, preg_replace('/[&]/', 'and', preg_replace('/[\']/', '', iconv('UTF-8', 'ASCII//TRANSLIT', $str))))), $delimiter));
    return $slug;

} 
Sign up to request clarification or add additional context in comments.

1 Comment

This is not an elegant snippet. preg_replace() can receive an array of finds/replacements, so nesting calls within calls unnecessarily bloats the line. & and ' don't need to be wrapped in braces -- there is no benefit to using a character class for the single symbol.
4

Previous one is good solution. But unfortunately it cuts off specific letters like ć or ż. If you want to keep them, then:

public static function createSlug($str, $delimiter = '-'){

    $unwanted_array = ['ś'=>'s', 'ą' => 'a', 'ć' => 'c', 'ç' => 'c', 'ę' => 'e', 'ł' => 'l', 'ń' => 'n', 'ó' => 'o', 'ź' => 'z', 'ż' => 'z',
        'Ś'=>'s', 'Ą' => 'a', 'Ć' => 'c', 'Ç' => 'c', 'Ę' => 'e', 'Ł' => 'l', 'Ń' => 'n', 'Ó' => 'o', 'Ź' => 'z', 'Ż' => 'z']; // Polish letters for example
    $str = strtr( $str, $unwanted_array );

    $slug = strtolower(trim(preg_replace('/[\s-]+/', $delimiter, preg_replace('/[^A-Za-z0-9-]+/', $delimiter, preg_replace('/[&]/', 'and', preg_replace('/[\']/', '', iconv('UTF-8', 'ASCII//TRANSLIT', $str))))), $delimiter));
    return $slug;
}

Comments

1
<?php
function createSlug($title) {

     $title = strtolower($title);

     $replacements = ['@'=> "at", '#' => "hash", '$' => "dollar", '%' => "percentage", '&' => "and", '.' => "dot", 
                '+' => "plus", '-' => "minus", '*' => "multiply", '/' => "devide", '=' => "equal to",
                '<' => "less than", '<=' => "less than or equal to", '>' => "greater than", '<=' => "greater than or equal to",
    ];

     $title = strtr($title, $replacements);
     return $urlKey = preg_replace('#[^0-9a-z]+#i', '-', $title);
}

echo createSlug("BLUE DIAMOND ALMONDS HONEY ROASTED @ 100 which is < 154");

// output :- blue-diamond-almonds-honey-roasted-at-100-which-is-less-than-154

for performance test case see this answer

You can test above function at onlinephp.io

2 Comments

Your function references the variable $str, but you don't ever use that var in your function. On top of that, you start by declaring $url, which references an undeclared var $title, to then never reference $url again, instead only referencing $title. This is cursed.
@Charbrec code fixed. now check it
0
<?php
function createSlug($str,$length,$delimiter = '-'){
    $slug = strtolower(trim(preg_replace('/[\s-]+/', $delimiter, preg_replace('/[^A-Za-z0-9-]+/', $delimiter, preg_replace('/[&]/', 'and', preg_replace('/[\']/', '', iconv('UTF-8', 'ASCII//TRANSLIT', $str))))), $delimiter));
    $slug = substr($slug, 0, $length);
    return $slug;
} 
$myString = "Lorem ipsum dolor sit amet consectetur adipiscing elit neque eleifend semper, lectus faucibus velit senectus risus felis malesuada habitant. Sollicitudin malesuada mus scelerisque eros primis dictum ultricies sagittis";
print createSlug($myString,50); // here 50 = 50 character length slug generate; you can change it 100/50/25 or etc
?>

Output: lorem-ipsum-dolor-sit-amet-consectetur-adipiscing-lorem-ipsum-dolor-sit-amet-consectetur-adipiscing

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.