Regola di riscrittura personalizzata per tipi di post personalizzati gerarchici
Sto lavorando al sito di un cliente e mi sono imbattuto nel mio peggior nemico... la riscrittura degli URL in WP :(. Non riesco proprio a capirlo e dopo molti giorni di tentativi e ricerche, non riesco a farlo funzionare.
Quello che sto cercando di ottenere è un permalink come questo company.com/prodotto/%nome-prodotto%/
indipendentemente dall'annidamento /genitore/figlio/
. Ho bisogno delle funzionalità delle pagine gerarchiche per altri motivi, ma non dovrebbero apparire nell'URL.
Ecco la mia configurazione:
- Wordpress 4.4.1
Impostazioni dei permalink impostate su
Nome articolo
Ho creato un tipo di post personalizzato gerarchico
prodotto
con il parametro rewrite impostato su false.$args = array( 'label' => __( 'Prodotto', 'domain' ), 'description' => __( 'Prodotti dell\'azienda', 'domain' ), 'labels' => $labels, 'supports' => array( 'title', 'editor', 'excerpt', 'thumbnail', 'revisions', 'page-attributes' ), 'taxonomies' => array( 'category', 'post_tag' ), 'hierarchical' => true, 'public' => true, 'show_ui' => true, 'show_in_menu' => true, 'menu_position' => 5, 'show_in_admin_bar' => true, 'show_in_nav_menus' => false, 'can_export' => true, 'has_archive' => true, 'exclude_from_search' => false, 'publicly_queryable' => true, 'rewrite' => false, 'capability_type' => 'page', ); register_post_type( 'prodotto', $args );
A questo punto i prodotti non hanno un permalink leggibile, appaino così e funzionano entrambi:
- Primo livello:
company.com/?prodotto=mio-primo-prodotto
-> ok - Secondo livello:
company.com/?prodotto=mio-primo-prodotto/prodotto-figlio
-> ok
Dopodiché, ho registrato la regola di riscrittura e il permastruct poi ho resettato le regole di riscrittura salvando le modifiche nella pagina delle impostazioni dei permalink
function bvt_product_rewrite_rule() {
add_rewrite_rule(
'^prodotto/([^/]+)/?$',
'index.php?post_type=prodotto&pagename=$matches[1]',
'top'
);
add_permastruct( 'prodotto', '/prodotto/%prodotto%/' );
}
add_action( 'init', 'bvt_product_rewrite_rule', 10 );
Ora i permalink venivano visualizzati correttamente per le pagine di primo livello ma non per le pagine figlie. Inoltre entrambi i livelli mi davano un errore 404.
- Primo livello:
company.com/prodotto/mio-primo-prodotto/
-> 404 - Secondo livello:
company.com/prodotto/mio-primo-prodotto/prodotto-figlio/
-> 404
Ho anche provato una soluzione data qui https://wordpress.stackexchange.com/a/101077/86838 che permetteva di rimuovere lo slug del genitore dal permalink del figlio, ma senza successo
function bvt_product_flatten_hierarchies( $post_link, $post ) {
if ( 'prodotto' != $post->post_type ) {
return $post_link;
}
$uri = '';
foreach ( $post->ancestors as $parent ) {
$uri = get_post( $parent )->post_name . "/" . $uri;
}
return str_replace( $uri, '', $post_link );
}
add_filter( 'post_type_link', 'bvt_product_flatten_hierarchies', 10, 2 );
Ho installato due plugin debug-bar e monkeyman-rewrite-analyzer per analizzare la riscrittura e la query, ma non riesco ancora a farlo funzionare.
Il mio ultimo tentativo è stato con il plugin wp-permastructure che permette di impostare permalink personalizzati per i tipi di post personalizzati. Questo abilita l'impostazione personalizzata permastruct
nell'array rewrite
dell'opzione register_post_type
.
[...]
'publicly_queryable' => true,
'rewrite' => array(
'permastruct' => '/%postname%/',
),
'capability_type' => 'page',
[...]
Con questa impostazione e disabilitando sia la riscrittura personalizzata che il flatten_hierarchies, ha funzionato come descritto dal plugin
- Primo livello:
company.com/mio-primo-prodotto/
-> ok - Secondo livello:
company.com/prodotto-figlio/
-> ok
Ma ora manca il livello /prodotto/
, e se provo a inserirlo nella configurazione 'permastruct' => '/prodotto/%postname%/'
mi riporta a un errore 404.
Il che mi porta alla mia domanda principale.
È possibile fare quello che ho bisogno o solo avvicinarmi come ho fatto con l'ultimo plugin?
Grazie già a chiunque prenderà il tempo di rispondermi, e magari salvarmi dalla mia povera situazione. Grazie
PS Non posso inserire più di due link nel corpo quindi ecco i link dei plugin menzionati:
https://wordpress.org/plugins/debug-bar/
https://wordpress.org/plugins/monkeyman-rewrite-analyzer/
https://wordpress.org/plugins/wp-permastructure/
Sei molto vicino. La tua regola di riscrittura sta usando la variabile di query sbagliata, pagename
dovrebbe essere semplicemente name
.
Ecco una versione che funziona per me su un'installazione pulita di WordPress 4.4.1 con il tema Twenty Sixteen:
function bvt_product_init() {
$args = array(
'label' => __( 'Prodotto', 'domain' ),
'description' => __( 'Prodotti dell\'azienda', 'domain' ),
'supports' => array( 'title', 'editor', 'excerpt', 'thumbnail', 'revisions', 'page-attributes' ),
'taxonomies' => array( 'category', 'post_tag' ),
'hierarchical' => true,
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'menu_position' => 5,
'show_in_admin_bar' => true,
'show_in_nav_menus' => false,
'can_export' => true,
'has_archive' => true,
'rewrite' => array( 'slug' => 'product' ),
);
register_post_type( 'product', $args );
add_rewrite_rule(
'^product/([^/]+)/?$',
'index.php?post_type=product&name=$matches[1]',
'top'
);
}
add_action( 'init', 'bvt_product_init' );
function bvt_product_flatten_hierarchies( $post_link, $post ) {
if ( 'product' != $post->post_type ) {
return $post_link;
}
$uri = '';
foreach ( $post->ancestors as $parent ) {
$uri = get_post( $parent )->post_name . "/" . $uri;
}
return str_replace( $uri, '', $post_link );
}
add_filter( 'post_type_link', 'bvt_product_flatten_hierarchies', 10, 2 );
Un potenziale problema da tenere presente: i tipi di post gerarchici ti permettono di creare post con lo stesso slug che hanno genitori diversi. Normalmente questo funziona perché vengono interrogati in base ai loro percorsi genitore/figlio. Senza avere questa relazione genitore/figlio nella struttura degli URL, puoi creare post che non potranno mai essere interrogati sul front-end se lo slug corrisponde a un post esistente. È solo qualcosa da tenere a mente.
