¿Cómo genera WordPress las URL amigables (slugs)?
Como señaló @SinisterBeard en su comentario muy válido a la pregunta ya hace un par de años, esta respuesta está desactualizada desde hace tiempo y las funciones mencionadas han sido reemplazadas por una API más nueva:
Consulta wp_unique_post_slug
.
Respuesta Original
De entrada, no puedo darte una página/tutorial/documentación sobre cómo se generan los slugs en WP, pero echa un vistazo a la función sanitize_title()
.
No te dejes confundir por el nombre de la función, no está destinada a sanitizar un título para usarlo posteriormente como título de página/post. Toma una cadena de título y la devuelve preparada para ser usada en una URL:
- elimina HTML & PHP
- elimina caracteres especiales
- convierte todos los caracteres a minúsculas
- reemplaza espacios en blanco, guiones bajos y puntos por guiones
- reduce múltiples guiones consecutivos a uno solo
Puede que haya casos extremos donde el núcleo haga algo adicional (tendrías que mirar el código fuente para verificar que sanitize_title()
siempre sea suficiente para generar exactamente lo que esperas), pero esto debería cubrir al menos el 99%, si no todos, los casos.

@kaiser: Supongo que simplemente estás enamorado de T5 Rewrite :) (que está en mi agenda para revisar) | y en general: Si un título es muy largo, WP también recorta los slugs a una longitud máxima determinada. Este es uno de esos casos donde no estoy completamente seguro si eso lo hace el filtro sanitize_title
que se aplica en la función, o si lo maneja algo más después de que la función ha terminado.

Supongo que es el filtro sanitize_title
el que hay que revisar. Pero también hay otras funciones relacionadas. Realmente no tengo idea sobre esto. A veces parece que SimplePie
es más fácil de entender que el asunto de WP_Rewrite
. Por cierto: Toscho está trabajando en integrar la funcionalidad del "Monkeyman Rewrite Analyzer" en su plugin. Ahí es donde las cosas empiezan a ponerse realmente interesantes.

También considera sanitize_title_with_dashes() si quieres ser un poco más explícito al generar un slug amigable para URLs.

Puedes usar esta función:
static public function slugify($text)
{
// reemplaza caracteres que no son letras o dígitos por -
$text = preg_replace('~[^\pL\d]+~u', '-', $text);
// translitera
$text = iconv('utf-8', 'us-ascii//TRANSLIT', $text);
// elimina caracteres no deseados
$text = preg_replace('~[^-\w]+~', '', $text);
// recorta
$text = trim($text, '-');
// elimina guiones duplicados
$text = preg_replace('~-+~', '-', $text);
// convierte a minúsculas
$text = strtolower($text);
if (empty($text)) {
return 'n-a';
}
return $text;
}
Funciona de manera muy similar a como lo hace la función de saneamiento de URLs de WordPress.

Me encontré con esto por casualidad hoy. Dices, "Es básicamente exactamente cómo funciona la función de saneamiento de URLs de wp". Entonces, dado que uno ya está en el contexto de ejecución de php enganchado a WordPress ya sea desde una cadena de llamadas basada en un tema o plugin, ¿Por qué razón concebible no se usaría simplemente una de las funciones relevantes de la API nativa sanitize*
? Ya disponible como una función gratuita en el espacio de nombres global, para bien o para mal. ¿Por qué recomendar agregar 503 bytes adicionales al código de distribución del ~fuente~ que duplican funcionalidad existente? ¿Solo porque es posible?

@JohannesPille según mi entendimiento, el OP quería tener un generador de slug
fuera de WP, pero asegurándose de que sus slugs generados fueran compatibles con WP. Si bien es cierto que esta funcionalidad ya existe en el código de WP, sin embargo, para usarla fuera de WordPress, significaría básicamente incluir casi todo el código de WP — que es sustancialmente más que 503 bytes de código :)

El núcleo a tu servicio
No hay un modo desarrollador integrado en WordPress aparte de WP_DEBUG
, que no te ayuda demasiado en este caso. Básicamente, WordPress utiliza la "API de Reescribir", que es un envoltorio de bajo nivel basado en funciones para la clase WP_Rewrite, sobre la cual puedes leer en el Codex</a>. El objeto <code>global $wp_rewrite
está a tu disposición para inspeccionarlo o interactuar con la clase.
Plugins que ayudan a analizarlo.
El plugin "T5 Rewrite" de Toschos y el plugin "Monkeyman Rewrite Analyzer" de Jan Fabry te guiarán en el camino. He escrito una pequeña extensión para "T5 Rewrite" para integrarlo sin problemas con el "Monkeyman Rewrite Analyzer", que puedes encontrar en el wiki del repositorio de "T5 Rewrite" aquí en GitHub.
El plugin "Monkeyman" añade una nueva página, ubicada en el menú de la interfaz de administración bajo Herramientas. El plugin "T5 Rewrite" añade una nueva pestaña de ayuda en la página Ajustes > Enlaces permanentes. Mi extensión también añade las pestañas de ayuda a la mencionada página de Herramientas.
Aquí hay una captura de pantalla de cómo se ve el contenido de la pestaña de ayuda del plugin "T5 Rewrite".
Vorlage = Patrón | Beschreibung = Explicación | Beispiele = Ejemplos
Notas
El plugin "T5 Rewrite" hace un trabajo maravilloso ayudándote a inspeccionar el objeto de reescritura. Y hace aún más: Añade nuevas posibilidades. Por eso es (al menos en mis instalaciones) parte de mi paquete básico de plugins.

Perdón por retomar una pregunta antigua, pero tuve la misma necesidad y descubrí que este método funciona perfectamente para mí:
$some_string = "DON'T STOP ME NOW!";
$slug = sanitize_title(sanitize_title($some_string, '', 'save'), '', 'query');
echo $slug; // dont-stop-me-now
Este método utiliza una doble sanitización.
La primera usa el modo save
, donde se eliminan las etiquetas HTML y PHP, y se quitan los acentos (los caracteres acentuados se reemplazan por sus equivalentes sin acento).
El segundo modo query
asegura que todos los espacios se reemplacen con guiones -
y se elimine otra puntuación.
¡Espero que esto ayude a alguien! :)

De hecho, si observas la función central wp_insert_post (post.php), verás que realiza lo siguiente:
$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 );
Lo clave a tener en cuenta es que utiliza tanto wp_unique_post_slug como sanitize_title:
wp_unique_post_slug( sanitize_title(
