Schimbarea structurii permalink pentru tipuri de postări personalizate
Am 2 tipuri de postări personalizate: software și hardware. Din motive SEO, aș dori ca permalink-urile paginilor individuale software și hardware să arate astfel:
https://domain.com/custom-post-name/
Dar în mod implicit WordPress adaugă slug-ul tipului de postare astfel:
https://domain.com/post-type-slug/custom-post-name/
Am eliminat slug-ul cu scriptul următor care face o înlocuire a șirului de caractere. Acum pagina individuală este accesibilă cu ambele URL-uri descrise mai sus și Google Search Console găsește 2 pagini cu exact același conținut, ceea ce nu este bun pentru SEO. Este posibil să schimb complet structura permalink-ului și să scap de slug-ul tipului de postare personalizat?
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' ),
)
);
Notă importantă despre răspunsul de mai sus:
Deși la prima vedere va funcționa corect, acest cod poate cauza probleme de performanță.
Tot acest cod va fi apelat pe hook-ul init, astfel încât la fiecare încărcare de pagină se va executa, iar flush_rules() este o operațiune foarte costisitoare din punct de vedere al timpului.
Prin urmare, este recomandat să apelați flush rules doar la activarea temei/plugin-ului. De asemenea, puteți utiliza funcțiile add_permastruct fără a fi nevoie să accesați global $wp_rewrite.
Soluția finală îmbunătățită ar fi:
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 );
}
/* în cazul unui plugin */
register_activation_hook(__FILE__,'my_custom_plugin_activate');
function my_custom_plugin_activate() {
flush_rewrite_rules();
}
/* în cazul unei teme personalizate în Functions.php */
add_action('after_switch_theme', 'mytheme_setup');
function mytheme_setup () {
flush_rewrite_rules();
}
Am reușit să rezolv problema folosind {$field_no_prefix}_save_pre cu post_name.
/**
* Personalizează permalink-urile.
*
* @param string $post_name
*
* @return string
* Returnează o combinație nume-SKU pentru produse, dacă toate componentele sunt disponibile.
*/
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(
{ modifică $_POST['post_title'] după preferințe }
);
return $post_name;
}
add_filter('name_save_pre', 'my_custom_permalinks', 1, 1);
Dacă te uiți la argumentul rewrite pentru register_post_type, există o opțiune with_front pentru a dezactiva baza implicită care este adăugată în fața permalink-ului tipului de postare personalizat. Dacă setezi aceasta la false, /blog/produse/ de exemplu devine /produse/.
https://developer.wordpress.org/reference/functions/register_post_type/#rewrite
'rewrite' => array(
'slug' => 'produse',
'with_front' => false
)
REZOLVAT
folosind $wp_rewrite poți adăuga o nouă structură de permalink
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();
}
apoi înlocuiești eticheta personalizată cu str_replace când filtrezi URL-ul linkului
add_filter( 'post_type_link', 'my_custom_permalinks', 10, 2 );
function my_custom_permalinks( $permalink, $post ) {
return str_replace( '%customname%/', $post->post_name, $permalink );
}
NOTĂ: dacă folosești această funcție așa cum este scrisă (eliminând slug-ul tipului de post din permalink), poți întâmpina probleme grave deoarece nu există control dacă faci un permalink personalizat la fel ca o pagină sau un post standard
Oricine ajunge la această întrebare și a întâmpinat problema linkurilor moarte cu "următorul script" menționat în întrebare, iată scriptul mulțumită Wayback Machine, cu o corecție la ceea ce cred că a fost o eroare în cod:
/**
* Elimină slug-ul din permalinkurile postărilor publicate. Afectează doar CPT-ul nostru.
*/
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 ) {
// Acționează doar pentru interogarea principală
if ( ! $query->is_main_query() )
return;
// Acționează doar pentru o potrivire specifică a regulii de rescriere
if ( 2 != count( $query->query )
|| ! isset( $query->query['page'] ) )
return;
// 'name' va fi setat dacă permalinkurile postărilor sunt doar post_name, altfel se va potrivi regula pentru pagină
if ( ! empty( $query->query['name'] ) )
$query->set( 'post_type', array( 'post', 'your_post_type', 'page' ) );
}
add_action( 'pre_get_posts', 'vipx_parse_request_tricksy' );
Împreună cu revizuirea lui Mikhail a soluției propuse de 3ky, dacă ați fost ca mine și nu v-a fost imediat evident, am considerat necesar să implementez funcția vipx_parse_request_tricksy() și acțiunea corespunzătoare. Dar funcția vipx_remove_cpt_slug() face același lucru ca my_custom_permalinks(), deci nu sunt necesare ambele - alegeți una?