Как WordPress генерирует URL-слаги?
Как отметил @SinisterBeard в своём вполне обоснованном комментарии к вопросу ещё пару лет назад, этот ответ давно устарел, и упомянутые функции были заменены новым API:
См. wp_unique_post_slug
.
Исходный ответ
Сразу скажу, что не могу дать вам страницу/руководство/документацию о том, как генерируются ЧПУ в WP, но взгляните на функцию sanitize_title()
.
Не дайте названию функции ввести вас в заблуждение — она не предназначена для очистки заголовка для дальнейшего использования в качестве заголовка страницы/записи. Она принимает строку заголовка и возвращает её, готовую для использования в URL:
- удаляет HTML и PHP
- удаляет специальные символы
- преобразует все символы в нижний регистр
- заменяет пробелы, подчёркивания и точки на дефисы
- сокращает множественные последовательные дефисы до одного
Возможно, есть крайние случаи, когда ядро делает что-то дополнительное (вам придётся проверить исходный код, чтобы убедиться, что sanitize_title()
всегда будет достаточно для генерации точно того, что вы ожидаете), но это должно покрыть как минимум 99%, если не все случаи.

@kaiser: Я понял, что ты просто влюблен в T5 Rewrite :) (это в моем списке на проверку) | и вообще: если заголовок действительно длинный, WP также обрезает слаги до определенной максимальной длины. Это один из тех случаев, когда я не совсем уверен, делается ли это фильтром sanitize_title
, применяемым в функции, или же это обрабатывается чем-то другим после выполнения функции.

Полагаю, нужно изучить фильтр sanitize_title
. Но есть и другие связанные функции. Я действительно не разбираюсь в этом. Иногда кажется, что SimplePie
проще понять, чем всю эту штуку с WP_Rewrite
. Кстати: Toscho работает над интеграцией функциональности "Monkeyman Rewrite Analyzer" в свой плагин. Вот где начинается самое интересное.

Также рассмотрите sanitize_title_with_dashes(), если хотите быть более явным в создании URL-дружественного слага.

Вы можете использовать эту функцию:
static public function slugify($text)
{
// заменяем все символы, не являющиеся буквами или цифрами, на -
$text = preg_replace('~[^\pL\d]+~u', '-', $text);
// транслитерируем
$text = iconv('utf-8', 'us-ascii//TRANSLIT', $text);
// удаляем нежелательные символы
$text = preg_replace('~[^-\w]+~', '', $text);
// обрезаем дефисы по краям
$text = trim($text, '-');
// удаляем повторяющиеся дефисы
$text = preg_replace('~-+~', '-', $text);
// приводим к нижнему регистру
$text = strtolower($text);
if (empty($text)) {
return 'n-a';
}
return $text;
}
Она работает практически так же, как функция санитизации URL в WordPress.

Случайно наткнулся на это сегодня. Вы говорите: «Это в точности то, как работает функция санации URL в WordPress». Тогда, учитывая, что мы уже находимся в контексте выполнения PHP, подключенного к WordPress через цепочку вызовов из темы или плагина, по какой мыслимой причине не использовать одну из соответствующих функций нативного API sanitize*
? Уже доступных как свободные функции в глобальном пространстве имен, хорошо это или плохо. Зачем рекомендовать добавлять дополнительные 503 байта в ~исходный~ распространяемый код, дублирующие существующую функциональность? Просто потому, что это возможно?

@JohannesPille, насколько я понял, автор вопроса хотел иметь генератор slug
вне WordPress, но при этом убедиться, что создаваемые slugs будут совместимы с WP. Хотя эта функциональность уже есть в коде WordPress, тем не менее, чтобы использовать её вне WordPress, пришлось бы подключать почти весь код WP — а это значительно больше, чем 503 байта кода :)

Ядро к вашим услугам
В WordPress нет встроенного режима разработчика, за исключением WP_DEBUG
, который в данном случае мало чем поможет. По сути, WP использует "Rewrite API" — функциональную низкоуровневую обёртку для WP_Rewrite
класса, о котором можно прочитать в Codex. Объект global $wp_rewrite
находится в вашем распоряжении для его изучения или взаимодействия с классом.
Плагины, которые помогают разобраться
Плагин Toschos "T5 Rewrite" и Плагин Яна Фабри "Monkeyman Rewrite Analyzer" помогут вам в этом. Я написал небольшое расширение для "T5 Rewrite", чтобы плавно интегрировать его с "Monkeyman Rewrite Analyzer", которое вы можете найти в вики репозитория "T5 Rewrite" здесь на GitHub.
Плагин "Monkeyman" добавляет новую страницу, расположенную в меню администратора в разделе Инструменты. Плагин "T5 Rewrite" добавляет новую вкладку справки на странице Настройки > Постоянные ссылки. Моё расширение также добавляет вкладки справки на упомянутую страницу Инструменты.
Вот скриншот содержимого вкладки справки плагина "T5 Rewrite".
Vorlage = Шаблон | Beschreibung = Описание | Beispiele = Примеры
Примечания
Плагин "T5 Rewrite" прекрасно справляется с задачей помощи в изучении объекта rewrite. И он делает даже больше: добавляет новые возможности. Поэтому он (по крайней мере в моих установках) входит в мой базовый набор плагинов.

Прошу прощения за возобновление старого вопроса, но у меня была такая же необходимость, и я обнаружил, что этот метод отлично работает для меня:
$some_string = "DON'T STOP ME NOW!";
$slug = sanitize_title(sanitize_title($some_string, '', 'save'), '', 'query');
echo $slug; // dont-stop-me-now
Этот метод использует двойную санитизацию.
Первая использует режим save
, в котором удаляются HTML и PHP теги, а также убираются акценты (акцентированные символы заменяются на их неакцентированные эквиваленты).
Второй режим query
гарантирует, что все пробелы заменяются на дефисы -
, а остальная пунктуация удаляется.
Надеюсь, это кому-то поможет! :)

Если посмотреть на основную функцию wp_insert_post (post.php), можно увидеть, что она выполняет следующее:
$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 );
Ключевой момент заключается в использовании как wp_unique_post_slug, так и sanitize_title:
wp_unique_post_slug( sanitize_title(
