Agregar base de categoría a URL en tipo de entrada/taxonomía personalizada

6 abr 2013, 18:59:28
Vistas: 127K
Votos: 45

Estoy construyendo un sistema tipo LMS en WordPress, controlado por Custom Post types. El tipo de entrada se llama Lessons (con un slug de courses) y tiene una taxonomía personalizada (categoría) llamada courses.

La estructura de URL del dominio se muestra actualmente como:

domain.example/courses/lesson-name.

Quiero que se convierta en:

domain.example/courses/[course-name{category}]/lesson-name

o esencialmente:

/[cpt]/%category%/%postname%/

Aquí está el plugin que escribí que está controlando los CPTs ahora.

function rflms_post_type() {
    $labels = array(
        'name'                => _x( 'Lessons', 'Post Type General Name', 'text_domain' ),
        'singular_name'       => _x( 'Lesson', 'Post Type Singular Name', 'text_domain' ),
        'menu_name'           => __( 'Lessons', 'text_domain' ),
        'parent_item_colon'   => __( 'Parent Product:', 'text_domain' ),
        'all_items'           => __( 'All Lessons', 'text_domain' ),
        'view_item'           => __( 'View Lesson', 'text_domain' ),
        'add_new_item'        => __( 'Add New Lesson', 'text_domain' ),
        'add_new'             => __( 'New Lesson', 'text_domain' ),
        'edit_item'           => __( 'Edit Lesson', 'text_domain' ),
        'update_item'         => __( 'Update Lesson', 'text_domain' ),
        'search_items'        => __( 'Search Lessions', 'text_domain' ),
        'not_found'           => __( 'No Lessons Found', 'text_domain' ),
        'not_found_in_trash'  => __( 'No Lessons Found in Trash', 'text_domain' ),
    );

    $args = array(
        'label'               => __( 'Lessons', 'text_domain' ),
        'description'         => __( 'Referable Lessons', 'text_domain' ),
        'labels'              => $labels,
        'hierarchical'        => false,
        'public'              => true,
        'show_ui'             => true,
        'show_in_menu'        => true,
        'show_in_nav_menus'   => true,
        'show_in_admin_bar'   => true,
        'supports'        => array('premise-member-access', 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments'),
        'menu_position'       => 5,
        'menu_icon'           => null,
        'can_export'          => true,
        'has_archive'         => true,
        'exclude_from_search' => false,
        'publicly_queryable'  => true,
        'capability_type'     => 'post',
        'rewrite'                    => array('slug' => 'courses'),
    );

    register_post_type( 'lessons', $args );

// Hook into the 'init' action

}
add_action( 'init', 'rflms_post_type', 0 );

// Register Custom Taxonomy
function custom_taxonomy()  {
    $labels = array(
        'name'                       => _x( 'Courses', 'Taxonomy General Name', 'text_domain' ),
        'singular_name'              => _x( 'Course', 'Taxonomy Singular Name', 'text_domain' ),
        'menu_name'                  => __( 'Courses', 'text_domain' ),
        'all_items'                  => __( 'All Courses', 'text_domain' ),
        'parent_item'                => __( 'Parent Course', 'text_domain' ),
        'parent_item_colon'          => __( 'Parent Course:', 'text_domain' ),
        'new_item_name'              => __( 'New Course Name', 'text_domain' ),
        'add_new_item'               => __( 'Add New Course', 'text_domain' ),
        'edit_item'                  => __( 'Edit Course', 'text_domain' ),
        'update_item'                => __( 'Update Course', 'text_domain' ),
        'separate_items_with_commas' => __( 'Separate Courses with commas', 'text_domain' ),
        'search_items'               => __( 'Search Courses', 'text_domain' ),
        'add_or_remove_items'        => __( 'Add or Remove Courses', 'text_domain' ),
        'choose_from_most_used'      => __( 'Choose from Most Used courses', 'text_domain' ),
    );

    $args = array(
        'labels'                     => $labels,
        'hierarchical'               => true,
        'public'                     => true,
        'show_ui'                    => true,
        'show_admin_column'          => true,
        'show_in_nav_menus'          => true,
        'show_tagcloud'              => false,
        'rewrite'                    => array('slug' => 'courses'),
    );

    register_taxonomy( 'course', 'lessons', $args );
}

// Hook into the 'init' action
add_action( 'init', 'custom_taxonomy', 0 );
3
Comentarios

Recientemente, me enfrenté a este problema. ¡Resuelto! #188834

maheshwaghmare maheshwaghmare
20 may 2015 10:03:35

¡SOLUCIÓN! (Después de una investigación interminable)<br/><br/>debes modificar el filtro post_type_link. más información en: http://wordpress.stackexchange.com/a/167992/33667 )

T.Todua T.Todua
26 jul 2015 23:06:09
Todas las respuestas a la pregunta 9
10
63

Cambia tu rewrite para añadir la variable de consulta del curso:

'rewrite' => array('slug' => 'cursos/%curso%')

Luego filtra post_type_link para insertar el curso seleccionado en el enlace permanente:

function wpa_enlace_post_curso( $enlace_post, $id = 0 ){
    $post = get_post($id);  
    if ( is_object( $post ) ){
        $terms = wp_get_object_terms( $post->ID, 'curso' );
        if( $terms ){
            return str_replace( '%curso%' , $terms[0]->slug , $enlace_post );
        }
    }
    return $enlace_post;  
}
add_filter( 'post_type_link', 'wpa_enlace_post_curso', 1, 3 );

También hay plugins como Custom Post Type Permalinks que pueden hacer esto por ti.

6 abr 2013 19:12:34
Comentarios

Gracias, aprecio tu rápida respuesta. Esto tiene mucho sentido. Sin embargo, tengo curiosidad, ¿dónde inserto el filtro post_type_link? ¿Puedo simplemente colocarlo al final de todo el documento?

Zach Russell Zach Russell
6 abr 2013 19:26:26

Lo agregué al final y la página da error 404.

Zach Russell Zach Russell
6 abr 2013 19:31:39

tienes que limpiar las reescrituras, visita la página de configuración de enlaces permanentes.

Milo Milo
6 abr 2013 20:09:58

también ten en cuenta que probablemente tendrás un conflicto entre una taxonomía y un tipo de publicación que comparten el mismo slug.

Milo Milo
6 abr 2013 20:13:20

Donde estoy ahora es que está generando los permalinks correctamente, pero no se está ejecutando como debería (está generando un soft 404). ¿Alguna recomendación sobre qué puedo hacer para que funcione correctamente? Soy consciente del flush de rewrites de los permalinks. Solo haz clic en 'guardar' y actualiza el archivo (es nginx así que se controla en el archivo nginx.conf)

Zach Russell Zach Russell
6 abr 2013 20:29:46

¡Lo tengo! Era un conflicto.

Zach Russell Zach Russell
6 abr 2013 20:37:28

Voto negativo - página de archivo 404

Brad Dalton Brad Dalton
4 abr 2020 04:06:27

Esto no funciona para publicaciones traducidas en un sitio multilingüe (por ejemplo, usando WPML).

montrealist montrealist
5 ago 2020 16:40:05

Esto me muestra la página de inicio en la URL recién creada. Debes usar add_rewrite_rule() como se ve en la respuesta de @Floris para que funcione. También ten en cuenta que las páginas de archivo dejan de funcionar, obtengo 404 para /mi-tipo-de-publicación y para /mi-tipo-de-publicación/mi-categoría

trainoasis trainoasis
1 sept 2020 10:16:49

Esto mostrará la publicación sin importar cuál sea el slug del curso. Se muestran en TODOS los slugs de cursos. ¿Cómo limitar esto para que solo se muestre en el slug del curso que está seleccionado y devuelva un 404 en los cursos que no están seleccionados para esa persona?

Solomon Closson Solomon Closson
16 jun 2021 01:27:23
Mostrar los 5 comentarios restantes
0
11

La solución para mí tuvo tres partes. En mi caso, el tipo de publicación se llama trainings (formaciones).

  1. Añadir 'rewrite' => array('slug' => 'trainings/%cat%') a la función register_post_type.
  2. Cambiar el slug para que tenga una categoría dinámica.
  3. "Escuchar" la nueva URL dinámica y cargar la plantilla adecuada.

Así es como cambiar el enlace permanente dinámicamente para un tipo de publicación dado. Añade esto a functions.php:

function vx_soon_training_post_link( $post_link, $id = 0 ) {
    $post = get_post( $id );
    if ( is_object( $post ) ) {
        $terms = wp_get_object_terms( $post->ID, 'training_cat' );
        if ( $terms ) {
            return str_replace( '%cat%', $terms[0]->slug, $post_link );
        }
    }

    return $post_link;
}

add_filter( 'post_type_link', 'vx_soon_training_post_link', 1, 3 );

...y así es como cargar la plantilla adecuada en la nueva URL dinámica. Añade esto a functions.php:

function archive_rewrite_rules() {
    add_rewrite_rule(
        '^training/(.*)/(.*)/?$',
        'index.php?post_type=trainings&name=$matches[2]',
        'top'
    );
    //flush_rewrite_rules(); // usar solo una vez
}

add_action( 'init', 'archive_rewrite_rules' );

¡Eso es todo! Recuerda actualizar los enlaces permanentes guardándolos nuevamente en el backend. O usa la función flush_rewrite_rules().

11 feb 2019 13:15:23
0

¡Solución encontrada!

Para tener enlaces permanentes jerárquicos para tipos de contenido personalizados, instala el plugin Custom Post Type Permalinks(https://wordpress.org/plugins/custom-post-type-permalinks/).

Actualiza el tipo de contenido registrado. En mi caso el tipo de contenido se llama "Help Center" (Centro de ayuda)

function help_centre_post_type(){
    register_post_type('helpcentre', array( 
        'labels'            =>  array(
            'name'          =>      __('Centro de Ayuda'),
            'singular_name' =>      __('Centro de Ayuda'),
            'all_items'     =>      __('Ver Artículos'),
            'add_new'       =>      __('Nuevo Artículo'),
            'add_new_item'  =>      __('Nuevo Centro de Ayuda'),
            'edit_item'     =>      __('Editar Centro de Ayuda'),
            'view_item'     =>      __('Ver Centro de Ayuda'),
            'search_items'  =>      __('Buscar en Centro de Ayuda'),
            'no_found'      =>      __('No se encontraron artículos'),
            'not_found_in_trash' => __('No hay artículos en la papelera')
                                ),
        'public'            =>  true,
        'publicly_queryable'=>  true,
        'show_ui'           =>  true, 
        'query_var'         =>  true,
        'show_in_nav_menus' =>  false,
        'capability_type'   =>  'page',
        'hierarchical'      =>  true,
        'rewrite'=> [
            'slug' => 'help-center',
            "with_front" => false
        ],
        "cptp_permalink_structure" => "/%help_centre_category%/%post_id%-%postname%/",
        'menu_position'     =>  21,
        'supports'          =>  array('title','editor', 'thumbnail'),
        'has_archive'       =>  true
    ));
    flush_rewrite_rules();
}
add_action('init', 'help_centre_post_type');

Y aquí está la taxonomía registrada

function themes_taxonomy() {  
    register_taxonomy(  
        'help_centre_category',  
        'helpcentre',        
        array(
            'label' => __( 'Categorías' ),
            'rewrite'=> [
                'slug' => 'help-center',
                "with_front" => false
            ],
            "cptp_permalink_structure" => "/%help_centre_category%/",
            'hierarchical'               => true,
            'public'                     => true,
            'show_ui'                    => true,
            'show_admin_column'          => true,
            'show_in_nav_menus'          => true,
            'query_var' => true
        ) 
    );  
}  
add_action( 'init', 'themes_taxonomy');

Esta línea hace que tu enlace permanente funcione

"cptp_permalink_structure" => "/%help_centre_category%/%post_id%-%postname%/",

Puedes eliminar %post_id% y dejar /%help_centre_category%/%postname%/"

No olvides actualizar los enlaces permanentes desde el panel de control.

6 oct 2017 14:39:43
2

Necesitas actualizar la línea donde has registrado un tipo de entrada personalizado usando la función register_post_type.

'rewrite' => array('slug' => 'courses/%cat%')

Para cambiar dinámicamente el enlace permanente del tipo de entrada, debes agregar este código en functions.php:

function change_link( $post_link, $id = 0 ) {
    $post = get_post( $id );
    if( $post->post_type == 'courses' )
    {
       if ( is_object( $post ) ) {
          $terms = wp_get_object_terms( $post->ID, array('course') );
          if ( $terms ) {
             return str_replace( '%cat%', $terms[0]->slug, $post_link );
         }
      }
    }
    return   $post_link ;
}
add_filter( 'post_type_link', 'change_link', 1, 3 );

//cargar la plantilla en la nueva URL generada, de lo contrario obtendrás errores 404 en la página

function generated_rewrite_rules() {
   add_rewrite_rule(
       '^courses/(.*)/(.*)/?$',
       'index.php?post_type=courses&name=$matches[2]',
       'top'
   );
}
add_action( 'init', 'generated_rewrite_rules' );

Después de eso, necesitas actualizar las reglas de reescritura de enlaces permanentes. Ve a wp-admin > Ajustes > Enlaces permanentes y actualiza la configuración de enlaces permanentes, luego presiona el botón "Guardar cambios". Esto generará URLs como esta: dominio.ejemplo/courses/[nombre-del-curso{categoría}]/nombre-de-la-lección

12 jun 2019 16:21:01
Comentarios

Voto negativo - Error 404 tanto en páginas individuales de CPT como en páginas de archivo de CTP

Brad Dalton Brad Dalton
4 abr 2020 04:07:21

@dev ¿seguiste todos los pasos que mencioné en mi respuesta? ¿has actualizado tus enlaces permanentes? Lo he probado y funciona correctamente.

Chetan Vaghela Chetan Vaghela
4 abr 2020 06:57:55
0

Para cualquiera interesado en la solución, sin tener que manipular código PHP directamente, recomiendo altamente el plugin Permalink Manager Lite de Maciej Bis. Es un salvavidas.

Tiene un mecanismo visual para eliminar o añadir cualquier parte que desees en la URL de los tipos de contenido personalizados basado en 'permastructs':

Captura de pantalla de Permalink Manager Lite

(Con todo el dolor que implica la simple estructuración de URLs con tipos de contenido personalizados, estábamos a punto de abandonar WP y mudarnos a otro CMS. Pero este plugin junto con ACF y CPTUI o Pods hace que Wordpress sea bastante profesional.)

1 jul 2019 06:50:24
0

¡Sí! Después de mucha investigación encontré el plugin 'Custom Permalinks'. Que cumple con mis requisitos en cuanto a URLs personalizadas, por ejemplo:

  • para Categorías
  • para Entradas
  • para Entradas Personalizadas
  • para Taxonomías Personalizadas etc.

Como este Post de Tipo Personalizado:

Ejemplo de URL personalizada para Post Type personalizado

20 may 2015 09:59:41
1

Esto funcionó para mí:

'rewrite' => array(
        'slug' => 'portfolio',
        'with_front' => false,
        'hierarchical' => true // para mostrar categoría/subcategoría
    ),
3 may 2017 20:17:57
Comentarios

Esto no hace uso de las categorías o su ruta, solo hace que el tipo de publicación personalizada sea jerárquico.

Joris Kroos Joris Kroos
25 ago 2017 14:53:22
0

Si estás usando get_post_type_archive_link(), quizás necesites eliminar /%cat%/ de la URL usando el filtro post_type_archive_link.

29 may 2020 19:33:42
0

Encontré la respuesta de @chetan-vaghela casi perfecta; en mi caso de uso también quería poder ver una lista de todas las publicaciones de este tipo de contenido como una página de archivo típica (es decir, /cursos/, sin ninguna taxonomía después). Solo tuve que agregar una regla de reescritura adicional de la siguiente manera:

function generated_rewrite_rules() {
    add_rewrite_rule(
        '^cursos/(.*)/(.*)/?$',
        'index.php?post_type=courses&name=$matches[2]',
        'top'
    );
}
18 ago 2020 13:07:15