Regulă personalizată de rescriere pentru tipuri de postări personalizate ierarhice
Lucrez la un site pentru un client și m-am lovit de cel mai mare dușman... rescrierea URL-urilor în WP :(. Chiar nu reușesc să îmi dau seama și după multe zile de încercări și căutări, nu reușesc să funcționeze.
Ceea ce încerc să obțin este un permalink de genul company.com/produs/%nume-produs%/
indiferent de adâncimea ierarhiei /părinte/copil/
. Am nevoie de funcționalitățile paginilor ierarhice din alte motive, dar acestea nu ar trebui să apară în URL.
Iată configurația mea:
- Wordpress 4.4.1
Setările de permalink setate la
Numele postării
Am creat un tip de postare ierarhic personalizat
produs
cu parametrul de rescriere setat pe false.$args = array( 'label' => __( 'Produs', 'domeniu' ), 'description' => __( 'Produsele companiei', 'domeniu' ), '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( 'produs', $args );
În acest moment produsele nu au un permalink frumos, arată astfel și funcționează ambele:
- Primul nivel:
company.com/?produs=primul-meu-produs
-> ok - Al doilea nivel:
company.com/?produs=primul-meu-produs/produs-copil
-> ok
După aceea, am înregistrat regula de rescriere și permastruct-ul, apoi am reîmprospătat regulile de rescriere salvând modificările în pagina de setări de permalink
function bvt_produs_rewrite_rule() {
add_rewrite_rule(
'^produs/([^/]+)/?$',
'index.php?post_type=produs&pagename=$matches[1]',
'top'
);
add_permastruct( 'produs', '/produs/%produs%/' );
}
add_action( 'init', 'bvt_produs_rewrite_rule', 10 );
Acum permalink-urile erau afișate corect pentru pagina de prim nivel, dar nu și pentru pagina copil. De asemenea, ambele niveluri mi-au dat eroare 404.
- Primul nivel:
company.com/produs/primul-meu-produs/
-> 404 - Al doilea nivel:
company.com/produs/primul-meu-produs/produs-copil/
-> 404
Am încercat și o soluție dată aici https://wordpress.stackexchange.com/a/101077/86838 care permite eliminarea slug-ului părinte din permalink-ul copilului, dar tot nu am reușit
function bvt_produs_flatten_hierarchies( $post_link, $post ) {
if ( 'produs' != $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_produs_flatten_hierarchies', 10, 2 );
Am instalat două plugin-uri debug-bar și monkeyman-rewrite-analyzer pentru a analiza rescrierea și interogarea, dar tot nu reușesc să le fac să funcționeze.
Ultima mea încercare a fost cu plugin-ul wp-permastructure care permite setarea de permalink-uri personalizate pentru tipurile de postări personalizate. Acesta activează setarea personalizată permastruct
în array-ul de opțiuni rewrite
al funcției register_post_type
.
[...]
'publicly_queryable' => true,
'rewrite' => array(
'permastruct' => '/%postname%/',
),
'capability_type' => 'page',
[...]
Cu această setare și ambele funcții personalizate de rescriere/permastruct/flatten_hierarchies dezactivate, a funcționat conform descrierii plugin-ului
- Primul nivel:
company.com/primul-meu-produs/
-> ok - Al doilea nivel:
company.com/produs-copil/
-> ok
Dar acum lipsește nivelul /produs/
, iar dacă încerc să îl adaug în configurația 'permastruct' => '/produs/%postname%/'
revin la eroarea 404 pentru ambele.
Ceea ce mă aduce la întrebarea principală.
Este posibil să fac ceea ce am nevoie sau doar ceea ce am reușit cu ultimul plugin?
Vă mulțumesc deja pentru oricine care își va lua timpul să îmi răspundă și poate mă va salva din situația mea nefericită. Mulțumesc
PS Nu pot insera mai mult de două link-uri în corp, așa că iată link-urile plugin-urilor menționate:
https://wordpress.org/plugins/debug-bar/
https://wordpress.org/plugins/monkeyman-rewrite-analyzer/
https://wordpress.org/plugins/wp-permastructure/
Ești aproape. Regula ta de rescriere folosește variabila de interogare greșită, pagename
ar trebui să fie doar name
.
Iată o versiune care funcționează pentru mine pe o instalare nouă de WordPress 4.4.1 și tema twentysixteen:
function bvt_product_init() {
$args = array(
'label' => __( 'Produs', 'domain' ),
'description' => __( 'Produsele companiei', '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 );
O problemă potențială de care trebuie să fii atent: tipurile de postări ierarhice îți permit să creezi postări cu același slug dar cu părinți diferiți. În mod normal, acest lucru funcționează pentru că sunt interogate pe baza căilor părinte/copil. Fără a avea această relație părinte/copil în structura URL-ului, poți crea postări care nu pot fi niciodată interogate în partea de frontend dacă slug-ul se potrivește cu o postare existentă. Doar ceva de ținut minte.
