Cambiar la estructura de enlaces permanentes para tipos de contenido personalizados

1 feb 2016, 18:59:28
Vistas: 22.6K
Votos: 2

Tengo 2 tipos de contenido personalizados: software y hardware. Por razones de SEO, me gustaría tener los enlaces permanentes de las páginas individuales de software y hardware así:

https://domain.com/nombre-post-personalizado/

Pero por defecto WordPress añade el slug del tipo de contenido así:

https://domain.com/slug-tipo-contenido/nombre-post-personalizado/

He eliminado el slug con este script que hace un reemplazo de la cadena. Ahora la página individual es accesible con ambas URLs descritas arriba y Google Search Console encuentra 2 páginas con exactamente el mismo contenido, lo cual no es bueno para el SEO. ¿Es posible cambiar la estructura completa del enlace permanente y eliminar el slug del tipo de contenido personalizado?

register_post_type( 'hardware',
    array (
        'labels' => $labels,
        'has_archive' => true,
        'public' => true,
        'supports' => array( 'title', 'editor', 'excerpt', 'custom-fields', 'thumbnail' ),
        'taxonomies' => array( 'hardware-post_tag', 'hardware-category' ),
        'exclude_from_search' => false,
        'capability_type' => 'post',
        'rewrite' => array( 'slug' => 'hardware' ),
    )
);

2
Comentarios

Por favor edita tu pregunta y dinos cómo utilizaste el register_post_type

WordPress Speed WordPress Speed
1 feb 2016 19:10:03

` //registrar tipo de post register_post_type( 'hardware', array ( 'labels' => $labels, 'has_archive' => true, 'public' => true, 'supports' => array( 'title', 'editor', 'excerpt', 'custom-fields', 'thumbnail' ), 'taxonomies' => array( 'hardware-post_tag', 'hardware-category' ), 'exclude_from_search' => false, 'capability_type' => 'post', 'rewrite' => array( 'slug' => 'hardware' ),

) ); `

Rico Rico
1 feb 2016 20:35:06
Todas las respuestas a la pregunta 5
0

Nota algo importante sobre la respuesta anterior:

Aunque funcionará bien a primera vista, causará problemas de rendimiento. Todo este código se ejecutará en el hook init, por lo que cada carga de página lo activará y flush_rules() consume mucho tiempo.

Por lo tanto, se recomienda llamar a flush rules solo durante la activación del tema/plugin. Además, puedes usar funciones add_permastruct sin necesidad de acceder a global $wp_rewrite.

La solución final mejorada sería:

add_action('init', 'my_custom_rewrite'); 
function my_custom_rewrite() {

    add_permastruct('hardware', '/%customname%/', false);
    add_permastruct('produkt', '/%customname%/', false);
}

add_filter( 'post_type_link', 'my_custom_permalinks', 10, 2 );
function my_custom_permalinks( $permalink, $post ) {
      return str_replace( '%customname%/', $post->post_name, $permalink );
}

 /* en caso de plugin */
register_activation_hook(__FILE__,'my_custom_plugin_activate');
function my_custom_plugin_activate() {
    flush_rewrite_rules();
}


/* en caso de tema personalizado en Functions.php */
add_action('after_switch_theme', 'mytheme_setup');
function mytheme_setup () {
    flush_rewrite_rules();
}
20 ene 2017 17:35:54
0

Logré resolverlo usando {$field_no_prefix}_save_pre con post_name.

/**
 * Personaliza los permalinks.
 *
 * @param string $post_name
 *
 * @return string
 *   Devuelve una combinación de nombre-SKU para productos, si todos los componentes están disponibles.
 */
function my_custom_permalinks( $post_name ) {

    if (
        ($_POST['post_type'] !== 'product')
    ||  ($_POST['post_status'] === 'auto-draft')
    ) {
        return $post_name;
    }

    $post_name = sanitize_title_with_dashes(
        { modifica $_POST['post_title'] como desees }
    );

    return $post_name;
}
add_filter('name_save_pre', 'my_custom_permalinks', 1, 1);
27 jul 2021 18:13:41
1

Si observas el argumento rewrite para register_post_type, existe una opción with_front para deshabilitar la base predeterminada que se antepone al enlace permanente del tipo de contenido personalizado. Si estableces esto como falso, /blog/productos/ por ejemplo se convierte en /productos/.

https://developer.wordpress.org/reference/functions/register_post_type/#rewrite

'rewrite' => array(
    'slug' => 'products',
    'with_front' => false
)
8 nov 2023 21:26:25
Comentarios

¡Respuesta tan simple y dulce!

brasofilo brasofilo
3 jul 2024 20:46:07
1

RESUELTO

con el uso de $wp_rewrite puedes agregar una nueva estructura de enlaces permanentes

add_action('init', 'my_custom_rewrite');
function my_custom_rewrite() {
    global $wp_rewrite;
    $wp_rewrite->add_permastruct('hardware', '/%customname%/', false);
    $wp_rewrite->add_permastruct('produkt', '/%customname%/', false);
    $wp_rewrite->flush_rules();
}

luego reemplazas tu etiqueta personalizada con str_replace cuando filtras la URL del enlace

add_filter( 'post_type_link', 'my_custom_permalinks', 10, 2 );
function my_custom_permalinks( $permalink, $post ) {
    return str_replace( '%customname%/', $post->post_name, $permalink );
}

NOTA: si usas esta función tal como está escrita (eliminando el slug del tipo de publicación del enlace permanente) puedes esperar problemas graves porque no hay control si haces un enlace permanente personalizado igual que una página o publicación estándar

2 feb 2016 19:04:27
Comentarios

Es una mala práctica actualizar las reglas en cada carga de página (acción init). Solo debes hacerlo una vez.

Serhiy Zaharchenko Serhiy Zaharchenko
8 abr 2020 13:06:37
0

Cualquiera que encuentre esta pregunta y haya sufrido el temido "link rot" con el enlace del "siguiente script" mencionado en la pregunta, aquí está el script cortesía de Wayback Machine, con una corrección a lo que creo que era un error en el código:

/**
 * Elimina el slug de los enlaces permanentes de posts publicados. Solo afecta a nuestro CPT (Custom Post Type).
 */
function vipx_remove_cpt_slug( $post_link, $post, $leavename ) {
    if ( ! in_array( $post->post_type, array( 'your_post_type' ) ) || 'publish' != $post->post_status )
        return $post_link;
    $post_link = str_replace( '/' . $post->post_type . '/', '/', $post_link );
    return $post_link;
}
add_filter( 'post_type_link', 'vipx_remove_cpt_slug', 10, 3 );

function vipx_parse_request_tricksy( $query ) {
    // Solo afecta la consulta principal
    if ( ! $query->is_main_query() )
        return;
    // Solo aplica para nuestra regla de rewrite muy específica
    if ( 2 != count( $query->query )
        || ! isset( $query->query['page'] ) )
        return;
    // 'name' estará definido si los permalinks son solo post_name, de lo contrario aplicará la regla de página
    if ( ! empty( $query->query['name'] ) )
        $query->set( 'post_type', array( 'post', 'your_post_type', 'page' ) );
}
add_action( 'pre_get_posts', 'vipx_parse_request_tricksy' );

Junto con la revisión de Mikhail de la solución propia de 3ky, si como a mí no te resultó inmediatamente obvio, encontré necesario implementar la función vipx_parse_request_tricksy() y su acción correspondiente. Pero la función vipx_remove_cpt_slug() duplica lo que hace my_custom_permalinks(), por lo que no son necesarias ambas — ¿elige una?

22 ene 2021 00:43:11