11

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
Robert Andrews
  • 1,209
  • 4
  • 23
  • 47
  • 1
    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? – Jonathan Kuhn Nov 16 '16 at 21:04
  • 2
    Pick a solution that's close to what you want, then modify it to add your special requirements. – Barmar Nov 16 '16 at 21:06
  • You could simply remove all the dashes from the result of a standard slug generator. – Barmar Nov 16 '16 at 21:07
  • 2
    There are libraries like https://github.com/cocur/slugify or https://github.com/ausi/slug-generator that allow you to customize the character translations and the delimiter. – ausi Oct 30 '17 at 22:17
  • @ausi, that's brilliant. Thanks. – Robert Andrews Oct 31 '17 at 08:30

4 Answers4

26

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;

} 
cmorrissey
  • 8,493
  • 2
  • 23
  • 27
  • 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. – mickmackusa Jan 06 '20 at 01:27
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;
}
Sjoerd Linders
  • 447
  • 5
  • 8
Amir Djaminov
  • 147
  • 1
  • 6
1
<?php
function createSlug($str) {

     $url = 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);
}

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

Harsh Patel
  • 1,032
  • 6
  • 21
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

Obaidul Haque
  • 916
  • 11
  • 18