Just a slug generator. I'm wondering if this can be simplified any further.
Many thanks.
<?php
function slug($string) {
// Replace all non letters, numbers, spaces or hypens
$string = preg_replace('/[^\-\sa-zA-Z0-9]+/', '', mb_strtolower($string));
// Replace spaces and duplicate hyphens with a single hypen
$string = preg_replace('/[\-\s]+/', '-', $string);
// Trim off left and right hypens
$string = trim($string, '-');
return $string;
}
echo slug('-- This is an example of an ------ article - @@@ ..,.:~&**%$£%$^*'); // outputs "this-is-an-example-of-an-article"
Updated version based on feedback:
<?php
function createSlug($slug) {
$lettersNumbersSpacesHyphens = '/[^\-\s\pN\pL]+/u';
$spacesDuplicateHypens = '/[\-\s]+/';
$slug = preg_replace($lettersNumbersSpacesHyphens, '', $slug);
$slug = preg_replace($spacesDuplicateHypens, '-', $slug);
$slug = trim($slug, '-');
return mb_strtolower($slug, 'UTF-8');
}
echo createSlug('-- This is an example ű of an ------ article - @@@ ..,.%&*£%$&*(*');
?>
2 Answers 2
You could create a few explanatory local variables:
$lettersNumbersSpacesHypens = '/[^\-\sa-zA-Z0-9]+/'; $spacesAndDuplicateHyphens = '/[\-\s]+/';
Usage:
$lettersNumbersSpacesHypens = '/[^\-\sa-zA-Z0-9]+/'; $slug = preg_replace($lettersNumbersSpacesHypens, '', mb_strtolower($slug)); $spacesAndDuplicateHyphens = '/[\-\s]+/'; $slug = preg_replace($spacesAndDuplicateHyphens, '-', $slug);
These would eliminate the comments. (I haven't checked the regexps, other names might be more appropriate.)
Reference: Chapter 6. Composing Methods, Introduce Explaining Variable in Refactoring: Improving the Design of Existing Code by Martin Fowler:
Put the result of the expression, or parts of the expression, in a temporary variable with a name that explains the purpose.
And Clean Code by Robert C. Martin, G19: Use Explanatory Variables.
slug
could be renamed tocleanSlug
(contains a verb) to describe what the function does.I'd rename the
$string
variable to$slug
It would be more descriptive, it would express the intent of the variable.I'd use a whitelist instead of the blacklist. Defining the allowed characters (A-Z, 0-9 etc) would create proper URLs from URLs which contain special characters like
é
orű
.
-
\$\begingroup\$ Thanks. I've updated my original question with some changes. Didn't notice the problem with different characters before, this has now been fixed. \$\endgroup\$Alex Garrett– Alex Garrett2014年03月14日 15:28:34 +00:00Commented Mar 14, 2014 at 15:28
-
\$\begingroup\$ @AlexGarrett: You're welcome. I've updated the answer a little bit. \$\endgroup\$palacsint– palacsint2014年03月14日 15:38:49 +00:00Commented Mar 14, 2014 at 15:38
Just a small extension to what has been written. If your slug generator is not for an assignment but for actual deployment a lot of frameworks use slug helpers already. I use Laravel, however Laravel has an entire class so that might be messy.
Before Laravel, Codeigniter was the rapid deploy system and their slug system is pretty robust.
Take a look at the slug file. Now mind you they have formatted it into a class with a lot of comments - but if you omit everything you can compare their's and yours and see where the middle ground can be.
Note - I'm adding this extra bit because as always you shouldn't re-engineer code if its been done and done well.
-
\$\begingroup\$ Great, thanks for the advice. I actually adapted this code from the Laravel framework. It's for education purposes, so wanted to simplify it so it's easier for beginners to grasp. But I completely agree, good hardened code shouldn't be rewritten if not necessary. \$\endgroup\$Alex Garrett– Alex Garrett2014年03月14日 15:30:19 +00:00Commented Mar 14, 2014 at 15:30
-
\$\begingroup\$ I recommend the codeigniter's version instead because i had to reverse engineer it for legacy non MVC code and it works better as as stand-alone function rather than a class (once you take out the clutter) \$\endgroup\$azngunit81– azngunit812014年03月14日 15:31:56 +00:00Commented Mar 14, 2014 at 15:31