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?
