Aggiungere la base della categoria all'URL in un custom post type/tassonomia
Sto costruendo un sistema tipo LMS in WordPress, controllato da Custom Post Type
.
Il post type si chiama Lessons
(con uno slug di courses
) e ha una tassonomia personalizzata
(categoria) chiamata courses
.
La struttura URL del dominio mostra attualmente:
domain.example/courses/lesson-name
.
Voglio che diventi:
domain.example/courses/[course-name{categoria}]/lesson-name
o essenzialmente:
/[cpt]/%category%/%postname%/
Ecco il plugin che ho scritto che sta controllando i CPT
ora.
function rflms_post_type() {
$labels = array(
'name' => _x( 'Lezioni', 'Nome Generale Tipo Post', 'text_domain' ),
'singular_name' => _x( 'Lezione', 'Nome Singolare Tipo Post', 'text_domain' ),
'menu_name' => __( 'Lezioni', 'text_domain' ),
'parent_item_colon' => __( 'Prodotto Genitore:', 'text_domain' ),
'all_items' => __( 'Tutte le Lezioni', 'text_domain' ),
'view_item' => __( 'Visualizza Lezione', 'text_domain' ),
'add_new_item' => __( 'Aggiungi Nuova Lezione', 'text_domain' ),
'add_new' => __( 'Nuova Lezione', 'text_domain' ),
'edit_item' => __( 'Modifica Lezione', 'text_domain' ),
'update_item' => __( 'Aggiorna Lezione', 'text_domain' ),
'search_items' => __( 'Cerca Lezioni', 'text_domain' ),
'not_found' => __( 'Nessuna Lezione Trovata', 'text_domain' ),
'not_found_in_trash' => __( 'Nessuna Lezione Trovata nel Cestino', 'text_domain' ),
);
$args = array(
'label' => __( 'Lezioni', 'text_domain' ),
'description' => __( 'Lezioni Referenziabili', '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 );
// Aggancio all'azione 'init'
}
add_action( 'init', 'rflms_post_type', 0 );
// Registra Tassonomia Personalizzata
function custom_taxonomy() {
$labels = array(
'name' => _x( 'Corsi', 'Nome Generale Tassonomia', 'text_domain' ),
'singular_name' => _x( 'Corso', 'Nome Singolare Tassonomia', 'text_domain' ),
'menu_name' => __( 'Corsi', 'text_domain' ),
'all_items' => __( 'Tutti i Corsi', 'text_domain' ),
'parent_item' => __( 'Corso Genitore', 'text_domain' ),
'parent_item_colon' => __( 'Corso Genitore:', 'text_domain' ),
'new_item_name' => __( 'Nome Nuovo Corso', 'text_domain' ),
'add_new_item' => __( 'Aggiungi Nuovo Corso', 'text_domain' ),
'edit_item' => __( 'Modifica Corso', 'text_domain' ),
'update_item' => __( 'Aggiorna Corso', 'text_domain' ),
'separate_items_with_commas' => __( 'Separa i Corsi con virgole', 'text_domain' ),
'search_items' => __( 'Cerca Corsi', 'text_domain' ),
'add_or_remove_items' => __( 'Aggiungi o Rimuovi Corsi', 'text_domain' ),
'choose_from_most_used' => __( 'Scegli tra i Corsi più usati', '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 );
}
// Aggancio all'azione 'init'
add_action( 'init', 'custom_taxonomy', 0 );

Modifica il tuo rewrite per aggiungere la variabile di query del corso:
'rewrite' => array('slug' => 'courses/%course%')
Poi filtra post_type_link
per inserire il corso selezionato nel permalink:
function wpa_course_post_link( $post_link, $id = 0 ){
$post = get_post($id);
if ( is_object( $post ) ){
$terms = wp_get_object_terms( $post->ID, 'course' );
if( $terms ){
return str_replace( '%course%' , $terms[0]->slug , $post_link );
}
}
return $post_link;
}
add_filter( 'post_type_link', 'wpa_course_post_link', 1, 3 );
Esistono anche plugin come Custom Post Type Permalinks che possono fare questo per te.

Grazie, apprezzo la tua rapida risposta. Ha perfettamente senso. Sono comunque curioso, dove devo inserire il filtro post_type_link? Posso semplicemente metterlo in fondo all'intero documento?

devi eseguire il flush delle rewrite rules, visita la pagina delle impostazioni dei permalink.

nota anche che è probabile che ci sia un conflitto tra una tassonomia e un tipo di post che condividono lo stesso slug.

Ora il punto in cui mi trovo è che sta generando i permalink correttamente, ma non li esegue come dovrebbe (restituisce un soft 404). Hai qualche consiglio su cosa posso fare per far funzionare tutto correttamente? Sono consapevole del flush dei rewrite dei permalink. Basta cliccare 'salva' e aggiorna il file (è nginx quindi è controllato nel file nginx.conf)

Questo non funziona per i post tradotti su un sito multilingue (ad esempio utilizzando WPML).

Questo mostra la pagina principale per me sul nuovo URL creato. Devi utilizzare add_rewrite_rule() come visto nella risposta di @Floris per farlo funzionare. Inoltre, nota che le pagine di archivio smettono di funzionare, ottengo 404 per /my-post-type e per /my-post-type/my-category

Questo mostrerà il post indipendentemente dallo slug del corso. Viene visualizzato su TUTTI gli slug dei corsi. Come limitarlo in modo che venga mostrato solo sullo slug del corso selezionato e restituisca un 404 per i corsi che non sono selezionati per quella persona?

La soluzione per me ha avuto tre parti. Nel mio caso il post type si chiama trainings
.
- Aggiungi
'rewrite' => array('slug' => 'trainings/%cat%')
alla funzioneregister_post_type
. - Modifica lo slug per avere una categoria dinamica.
- "Ascolta" il nuovo URL dinamico e carica il template appropriato.
Ecco come modificare dinamicamente il permalink per un determinato post type. Aggiungi 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 );
...e questo è come caricare il template appropriato sul nuovo URL dinamico. Aggiungi a functions.php
:
function archive_rewrite_rules() {
add_rewrite_rule(
'^training/(.*)/(.*)/?$',
'index.php?post_type=trainings&name=$matches[2]',
'top'
);
//flush_rewrite_rules(); // usare solo una volta
}
add_action( 'init', 'archive_rewrite_rules' );
Questo è tutto! Ricordati di aggiornare i permalink salvandoli nuovamente nel backend. Oppure usa la funzione flush_rewrite_rules()
.

Ho trovato la soluzione!
Per avere permalink gerarchici per i custom post type installa il plugin Custom Post Type Permalinks(https://wordpress.org/plugins/custom-post-type-permalinks/).
Aggiorna il post type registrato. Io ho un post type chiamato help center
function help_centre_post_type(){
register_post_type('helpcentre', array(
'labels' => array(
'name' => __('Help Center'),
'singular_name' => __('Help Center'),
'all_items' => __('Visualizza Articoli'),
'add_new' => __('Nuovo Articolo'),
'add_new_item' => __('Nuovo Help Center'),
'edit_item' => __('Modifica Help Center'),
'view_item' => __('Vedi Help Center'),
'search_items' => __('Cerca Help Center'),
'no_found' => __('Nessun Articolo Trovato'),
'not_found_in_trash' => __('Nessun Articolo nel Cestino')
),
'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');
Ed ecco la tassonomia registrata
function themes_taxonomy() {
register_taxonomy(
'help_centre_category',
'helpcentre',
array(
'label' => __( 'Categorie' ),
'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');
Questa riga rende funzionanti i tuoi permalink
"cptp_permalink_structure" => "/%help_centre_category%/%post_id%-%postname%/",
Puoi rimuovere %post_id%
e tenere /%help_centre_category%/%postname%/"
Non dimenticare di svuotare i permalink dalla dashboard.

Devi aggiornare la riga dove hai registrato un custom post type utilizzando la funzione register_post_type
.
'rewrite' => array('slug' => 'courses/%cat%')
Per cambiare dinamicamente il permalink del post type, devi aggiungere questo codice nel file 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 );
//carica il template sul nuovo URL generato altrimenti otterrai errori 404
function generated_rewrite_rules() {
add_rewrite_rule(
'^courses/(.*)/(.*)/?$',
'index.php?post_type=courses&name=$matches[2]',
'top'
);
}
add_action( 'init', 'generated_rewrite_rules' );
Dopodiché, devi ripulire i permalink riscritti. Vai su wp-admin > Impostazioni > permalink e aggiorna le impostazioni dei permalink poi premi il pulsante "Salva modifiche". Genererà URL come questo: dominio.esempio/courses/[nome-corso{categoria}]/nome-lezione

Per chiunque sia interessato alla soluzione, senza dover pasticciare con codice PHP grezzo, consiglio vivamente il plugin Permalink Manager Lite di Maciej Bis. È un salva-vita.
Dispone di un meccanismo visivo per rimuovere o aggiungere qualsiasi parte desiderata nell'URL dei custom post type basato sui 'permastruct':
(Con tutta la fatica coinvolta nella semplice strutturazione degli URL con i custom post type, stavamo per abbandonare WP e passare a un altro CMS. Ma questo plugin, insieme ad ACF e CPTUI o Pods, rende Wordpress abbastanza professionale.)

Sì! Dopo molte ricerche ho trovato il plugin 'Custom Permalinks'. Che soddisfa la mia esigenza riguardo agli URL personalizzati, ad esempio:
- per le Categorie
- per gli Articoli
- per i Custom Post
- per le Tassonomie Personalizzate ecc.
Come questo Custom Post Type - Post:

Ho trovato la risposta di @chetan-vaghela quasi perfetta; nel mio caso d'uso volevo anche poter vedere un elenco di tutti i post di questo tipo di contenuto come una tipica pagina archivio (es. /corsi/, senza alcuna tassonomia dopo). Ho dovuto solo aggiungere una regola di riscrittura aggiuntiva come segue:
function generated_rewrite_rules() {
add_rewrite_rule(
'^corsi/(.*)/(.*)/?$',
'index.php?post_type=courses&name=$matches[2]',
'top'
);
}
