Is there a page somewhere that details exactly how WordPress generates slugs for URLs? I'm writing a script that needs to generate URL slugs identical to the ones WordPress generates.
-
The answers to this question are now outdated - use codex.wordpress.org/Function_Reference/wp_unique_post_slug instead.– SinisterBeardCommented May 5, 2016 at 9:33
-
@SinisterBeard Came across this by chance today. You would have been very welcome to either add a new answer or to edit the accepted one. Will update it now. Better late than never. Thanks for making a valid point.– Johannes PilleCommented Aug 30, 2020 at 12:39
5 Answers
As per @SinisterBeard's very valid comment to the question already a couple of years back now, this answer has long been outdated and the mentioned function(s) hence been replaced by a newer API:
See wp_unique_post_slug
.
Original Answer
Off the bat, I can't give you a page/tutorial/documentation on how WP slugs are generated, but take a look at the sanitize_title()
function.
Don't get a wrong impression by the function name, it is not meant to sanitize a title for further usage as a page/post title. It takes a title string and returns it to be used in a URL:
- strips HTML & PHP
- strips special chars
- converts all characters to lowercaps
- replaces whitespaces, underscores and periods by hyphens/dashes
- reduces multiple consecutive dashes to one
There might be edge cases where the core does something additional (you'd have to look at the source to verify that sanitize_title()
will always suffice in generating exactly the same you expect), but this should cover at least 99%, if not all, cases.
-
1@kaiser: I figured you're simply in love with T5 Rewrite :) (which is on my agenda to check out) | and generally: If a title is really long, WP also trims slugs to a certain maximum length. That's one of those cases where I am not entirely sure whether that's done by the
sanitize_title
filter applied in the function as well, or whether that's handled by something else after the function has run. Commented Nov 30, 2012 at 18:24 -
I guess it's the
sanitize_title
-filter that one needs to check out. But there're also other related functions. I really got no idea about this. Sometimes it seemsSimplePie
is easier to understand than theWP_Rewrite
thing. Btw: Toscho works on integrating the "Monkeyman Rewrite Analyzer"-functionality into his plugin. That's where things start to really get interesting.– kaiserCommented Nov 30, 2012 at 18:52 -
3Also consider sanitize_title_with_dashes() if you want to be a little more explicit about generating a URL-friendly slug. Commented Dec 9, 2014 at 16:17
You can use this function:
static public function slugify($text)
{
// replace non letter or digits by -
$text = preg_replace('~[^\pL\d]+~u', '-', $text);
// transliterate
$text = iconv('utf-8', 'us-ascii//TRANSLIT', $text);
// remove unwanted characters
$text = preg_replace('~[^-\w]+~', '', $text);
// trim
$text = trim($text, '-');
// remove duplicate -
$text = preg_replace('~-+~', '-', $text);
// lowercase
$text = strtolower($text);
if (empty($text)) {
return 'n-a';
}
return $text;
}
Its kind of exactly how the wp url sanitize function works.
-
3Came across this by chance today. You say, "Its kind of exactly how the wp url sanitize function works." Then, given that one is already in the context of php execution hooked into some WordPress either from a theme- or plugin-based call chain, For what thinkable reason would one not simply use one of the relevant functions of the native
sanitize*
API? Already available as a free function in the global namespace, for better or for worse. Why recommend adding an additional 503 bytes to the ~source~ distribution code that duplicate existing functionality? Just because it's possible? Commented Aug 30, 2020 at 12:35 -
@JohannesPille in my understanding, the OP wanted to have a
slug
generator outside of WP, but still making sure that his generated slugs would be WP-compatible. While it's true that this functionality already exists in the WP code, nevertheless, to use it outside WordPress, it would mean basically including almost all the WP code — which is substantially more than 503 bytes of code :) Commented Apr 10, 2023 at 10:20
Core at your service
There's no developer mode built into WordPress aside from WP_DEBUG
, which doesn't help you too much in this case. Basically WP uses the "Rewrite API", which is a function based, low level wrapper for the WP_Rewrite
class, which you can read about in Codex. The global $wp_rewrite
object stands at your service to inspect it or interact with the class.
Plugins that help looking into it.
Toschos "T5 Rewrite"-Plugin and Jan Fabrys "Monkeyman Rewrite Analyzer"-Plugin will guide you your way. I've written a small extension for "T5 Rewrite" to smoothly integrate it with the "Monkeyman Rewrite Analyzer", which you can find in the "T5 Rewrite" repos wikie here on GitHub.
The "Monkeyman"-plugin adds a new page, filed in the admin UI menu under Tools. The "T5 Rewrite"-plugin adds a new help tab to the Settings > Permalinks page. My extension adds the help tabs to the mentioned Tools-page too.
Here's a screenshot of what the "T5 Rewrite"-plugins help tab content looks like.
Vorlage = Pattern | Beschreibung = Explanation | Beispiele = Examples
Notes
The "T5 Rewrite"-plugin does a wonderful job with helping you inspect the rewrite object. And it does even more: It adds new possibilities. Therefore it's (at least in my installations) part of my basic plugins package.
Forgive for resuming an old question, but I had the same necessity as found out this method works perfectly for me:
$some_string = "DON'T STOP ME NOW!";
$slug = sanitize_title(sanitize_title($some_string, '', 'save'), '', 'query');
echo $slug; // dont-stop-me-now
This method uses a double sanitization.
The first one uses the save
mode, where HTML and PHP tags are stripped, and accents are removed (accented characters are replaced with non-accented equivalents).
The second query
mode ensures all spaces are replaced with dashes -
and other punctuation removed.
Hope this helps someone! :)
Actually, if you look core function wp_insert_post (post.php), you will see that it does the following:
$data['post_name'] = wp_unique_post_slug( sanitize_title( $data['post_title'], $post_ID ), $post_ID, $data['post_status'], $post_type, $post_parent );
$wpdb->update( $wpdb->posts, array( 'post_name' => $data['post_name'] ), $where );
The key thing to note is that uses both wp_unique_post_slug and sanitize_title:
wp_unique_post_slug( sanitize_title(