Regenerar Slugs desde el Título de las Entradas

19 mar 2012, 18:38:12
Vistas: 26.3K
Votos: 17

¿Es posible regenerar los slugs programáticamente después de cambiar los títulos de las entradas? Se actualizaron numerosos títulos de entradas y el slug no se actualizó con el título, por lo que necesito regenerar todos estos slugs.

1
Comentarios

He tenido que hacer esto varias veces y he descubierto que, en diferentes entornos de servidor donde no pueden manejar arrays grandes (con numberposts configurado como ilimitado) ni llamar a wp_update_post repetidamente con un alto consumo de memoria, dividirlo en una llamada WP_Query con paginación y usar $wpdb es más manejable y eficiente. Proporcioné el ejemplo de código en una publicación similar.

codearachnid codearachnid
27 feb 2014 05:14:30
Todas las respuestas a la pregunta 5
3
28

Sí, es posible.

Código de ejemplo, debe ser probado y refinado:

// obtener todas las publicaciones
$posts = get_posts( array (  'numberposts' => -1 ) );

foreach ( $posts as $post )
{
    // verificar el slug y ejecutar una actualización si es necesario 
    $new_slug = sanitize_title( $post->post_title );
    if ( $post->post_name != $new_slug )
    {
        wp_update_post(
            array (
                'ID'        => $post->ID,
                'post_name' => $new_slug
            )
        );
    }
}

Acabo de inventar esto, probablemente hay algunos errores y casos excepcionales, pero debería darte una idea. Además, esto puede tomar un tiempo, por lo que podría ser útil dividir la actualización en partes más pequeñas.

19 mar 2012 21:20:32
Comentarios

Hmm... según mi experiencia, esto no funciona. El argumento post_name es ignorado por wp_update_post, al menos en la versión 3.9 del núcleo

Alexandre Bourlier Alexandre Bourlier
4 sept 2014 16:55:37

Actualmente, post_name es ignorado dentro de la función wp_update_post(), pero se toma en consideración cuando la actualización del post llama a la función wp_insert_post(): esto significa que pasar el nuevo slug a la actualización, resultará en un cambio efectivo del mismo para el post que se está actualizando.

Erenor Paz Erenor Paz
30 may 2018 11:00:27

@fuxia, he intentado algo similar pero se agota el tiempo. ¿Podrías sugerir un enfoque?

Motivated Motivated
5 oct 2022 08:39:53
0

Este complemento también hace el trabajo: http://www.jerrytravis.com/598/wordpress-plugin-to-generate-post-slugs

Sin embargo, como solo lo hace para publicaciones que aún no tienen un slug, si necesitas regenerar los slugs edita la siguiente línea en el complemento:

if ($post->post_name == "") {

por ejemplo, podrías cambiarlo a:

if (true) {

24 jul 2014 11:31:09
2

Estaba probando el método sugerido por Toscho, que es el "instintivo", pero en muchos casos no funciona (consulta el código del núcleo para entender a qué me refiero con "muchos casos").

Al revisar el código, encontré el gancho de filtro wp_insert_post_data, llamado por la función wp_update_post justo antes de insertar la publicación en la base de datos.

Al llamar a este filtro y cambiar el valor de $data['post_name'], logré que esto funcionara correctamente. WordPress es genial pero está tan mal documentado...

Edité la documentación, para que más personas puedan encontrar esta solución si la necesitan.

4 sept 2014 17:30:06
Comentarios

¿Puedes señalar por qué wp_update_post sobrescribe el post_name? La única razón que veo para que esto suceda es si el usuario que intenta modificar el post_name es solo un colaborador (o mismo nivel), en cuyo caso no debería permitir que ese usuario cambie el slug, ¿encontraste algún otro caso en el que el post_name se sobrescriba?

jnhghy - Alexandru Jantea jnhghy - Alexandru Jantea
16 oct 2014 10:32:59

Sí, esta es la forma correcta de hacerlo. Gracias @Alexandre

User User
10 mar 2017 10:44:41
0

Puedes hacer esto directamente en MySQL si lo necesitas. (Nuestro sitio WooCommerce tiene cientos de miles de productos):

update wp_posts set post_name = concat(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(lower(post_title), '"', ''), "'", ''), ",", '-'), " ", '-'), "&", ''), ";", ''), "@", ''), ".", ''), ":", ''), "/", ''), "+", ''), "(", ''), ")", ''), "--", '-'), "---", '-'), "--", '-'), "--", '-'), '-', id) where post_type = 'product';

where post_type = 'product' - esto limitará la actualización solo a los productos de WooCommerce; deberías determinar qué límites quieres establecer en esta consulta.

7 ene 2020 07:19:26
0

Tuvimos un problema donde estábamos migrando y combinando varios tipos de entradas. También teníamos varios títulos en blanco. Escribí un comando WP CLI para solucionarlos todos, pero esta es la esencia de lo que hice:

    global $wpdb;
    $types = [
      'page',
      // Tus nombres máquina de CPT
    ];

    // Formatea nuestra consulta IN correctamente.
    $final = array_map(function($type) {
      return "'" . esc_sql($type) . "'";
    }, $types);

    // Recupera todos nuestros campos de título vacíos.
    $query = sprintf("SELECT post_title, ID FROM `%s` WHERE post_type IN (%s) AND post_name = ''",
      $wpdb->posts,
      implode(",", $final)
    );

    foreach ($wpdb->get_results($query) as $post) {
      $title = sanitize_title_with_dashes( $post->post_title );
      $wpdb->update('wp_posts', ['post_name' => $title], ['ID' => $post->ID]);
    }

Fue necesario hacer una actualización directa en MySQL ya que wp_update_post no actualiza el post_name.

12 jun 2020 16:44:19