Cum să dezactivezi vizualizarea individuală pentru un tip de postare personalizat?
Având acest tip de postare personalizat:
register_post_type(
'sample_post_type',
[
'labels' => [
'name' => _x('Postări Exemplu', 'nume general tip postare'),
'singular_name' => _x('Postare Exemplu', 'nume singular tip postare'),
],
'public' => true,
'show_in_nav_menus' => false,
'exclude_from_search' => true,
]
);
Cum pot dezactiva vizualizarea individuală pentru acest tip specific de postare? Este în regulă să afișez o simplă pagină 404 sau să redirecționez către pagina principală. Deoarece aceasta este un plugin, nu pot crea un fișier single-sample_post_type.php
pentru a configura o pagină goală.

Pare a fi soluția pentru a opri CPT-ul tău din crearea de pagini web reale, păstrând în același timp toate referințele din baza de date.

Pentru a dezactiva vizualizarea individuală pentru un CPT (Custom Post Type) poți fie să redirecționezi utilizatorii către o anumită URL, fie să o dezactivezi în momentul înregistrării CPT-ului.
METODA 1:
Redirecționare vizualizare individuală CPT către o URL personalizată, pagina de arhivă rămâne accesibilă public.
Poți folosi hook-ul template_redirect
pentru a redirecționa un utilizator, poți folosi orice URL în loc de home_url()
și codul de eroare dorit ca al doilea argument.
<?php
add_action( 'template_redirect', 'wpse_128636_redirect_post' );
function wpse_128636_redirect_post() {
if ( is_singular( 'tip_postare_exemplu' ) ) :
wp_redirect( home_url(), 301 );
exit;
endif;
}
?>
METODA 2:
Dezactivare completă a paginii Individuale și a Arhivei pe front-end; Funcționează doar pentru Post Types personalizate.
O alternativă este să setezi publicly_queryable
la false în momentul înregistrării postului personalizat.
'publicly_queryable' => false
Această opțiune ascunde atât pagina individuală cât și cea de arhivă pentru CPT, poate fi folosită doar pentru postări personalizate.
Chiar dacă arhiva și vizualizarea individuală sunt ascunse, poți totuși să adaugi un șablon de pagină sau un bloc personalizat pentru a lista postările dacă este necesar.

O soluție bună. Am considerat util să efectuez această redirecționare doar pentru utilizatorii neautentificați, verificând dacă get_current_user_id()
returnează 0.

de ce să nu folosești doar is_singular('post-type-slug')
în condiția if()
în loc de 2 condiții?

sugestia cu remove_rewrite_tag( '%post-type-slug%' ) este o soluție bună

Am testat toate soluțiile menționate mai sus și soluția reală este mai simplă decât orice redirecționare sugerată.
Pentru a avea arhiva accesibilă și pentru a lista elementele, iar postarea individuală să nu fie accesibilă și să redirecționeze automat la 404, setați
'query_var' => false
când înregistrați tipul de postare personalizat (CPT). Dacă setați publicly_queryable
la false, arhivele vor fi redirecționate către pagina principală, nicio altă combinație nu va funcționa. Setează query_var
la false și asta este tot.
Aici este un exemplu complet de CPT https://gist.github.com/danyj/bfd038d3c8d578548c4d700bd0a7942a
vezi linia 50 https://gist.github.com/danyj/bfd038d3c8d578548c4d700bd0a7942a#file-thz_cpt_items_single_view_redirect-php-L50
după cum este menționat aici
https://codex.wordpress.org/Function_Reference/register_post_type
Notă: Dacă query_var este gol, null sau boolean FALSE, WordPress va încerca în continuare să-l interpreteze (4.2.2) și previzualizările/vizualizările postării personalizate vor returna eroarea 404.

Se simte un pic ca un hack, dar pare să funcționeze. Aș fi vrut să adauge o proprietate dedicată has_single, alături de proprietatea existentă has_archive.

Bună, am încercat să fac același lucru dar nu a funcționat. În ciuda faptului că am adăugat query_var
la false
, încă pot accesa linkurile către paginile single. Poți să mă ajuți?

@iSaumya încearcă să resetezi permalinkurile (accesează pagina de permalinkuri și salvează din nou) sau folosește comanda wp-cli wp rewrite flush && wp cache flush

Nu mai funcționează (august 2022). Nota care menționa că vizualizările individuale au fost eliminate nu mai există nici în documentație.

@blorf nota încă se află în documentație - este listată sub publicly_queryable

Pentru mine funcționează, folosesc Elementor cu JetEngine și configurez tipul de postare cu public
, publicly_queryable
și has_archive
setate pe true, iar query_var
pe false. Arhivele mele funcționează, iar postările individuale redirecționează 301 către pagina principală.

O modalitate mai simplă de a face acest lucru poate fi prin transmiterea următoarelor argumente la înregistrarea Tipului de Postare Personalizat
register_post_type('sample_post_type',array(
'labels' => array(
'name' => _x('Postări Exemplu', 'nume general tip postare'),
'singular_name' => _x('Postare Exemplu', 'nume singular tip postare')
),
'public' => true,
'exclude_from_search' => true,
'show_in_admin_bar' => false,
'show_in_nav_menus' => false,
'publicly_queryable' => false,
'query_var' => false
));

De fapt, ai nevoie ca publically_querable
să fie setat pe true pentru ca Arhivele Tipului de Post să funcționeze.

Nu funcționează pentru mine. Doar redirecționează înapoi către pagina principală când încerc să accesez arhiva

Unu. Din fișierul tău de funcții.
add_action( 'template_redirect', 'redirect_cpt_singular_posts' );
function redirect_cpt_singular_posts() {
if ( is_singular('your-cpt-slug') ) {
wp_redirect( home_url(), 302 );
exit;
}
}
Doi. Din fișierul tău single.cpt.php:
<?php wp_redirect( home_url() ); exit; ?>

Mi-a plăcut a doua opțiune. Dar trebuie să știu dacă există vreun dezavantaj cu această a doua opțiune.

@user2584538 Dacă nu ai un fișier personalizat single-cpt_name.php
, nu ai putea face asta. Dacă pui funcția într-un simplu fișier de plugin, ai putea activa/dezactiva fără a edita vreun fișier.

Bazându-mă pe răspunsul foarte bun al lui Sven, am rescris funcția lui pentru a face mai ușor adăugarea mai multor tipuri de posturi folosind in_array()
în declarația if și apoi redirecționând către pagina de arhivă în loc de pagina principală.
(apropo, cred că setarea query_var
și/sau publically_queryable
la false va dezactiva nu doar vizualizările individuale, dar și vizualizarea nativă de arhivă, suprascriind 'has_archive' => true
. În acest caz, poți încă să configurezi un WP_query personalizat și să creezi propria pagină de arhivă, într-un template, dar interogarea principală nu va mai face asta, nu-i așa?)
function fq_disable_single_cpt_views() {
$queried_post_type = get_query_var('post_type');
$cpts_without_single_views = array( 'my-post-type', 'my-other-post-type' );
if ( is_single() && in_array( $queried_post_type, $cpts_without_single_views ) ) {
wp_redirect( home_url( '/' . $queried_post_type . '/' ), 301 );
exit;
}
}
add_action( 'template_redirect', 'fq_disable_single_cpt_views' );

a fost o idee bună, dar nu funcționează dacă schimbi redirectarea pentru CPT-uri

Am modificat linia ta wp_redirect în wp_redirect( get_post_type_archive_link( $queried_post_type ), 301 );
funcționează perfect!

În cazul în care doriți să dezactivați complet vizualizarea individuală a tipului de postare personalizată pe frontend, dar să păstrați posibilitatea de a afișa pagina de arhivă, lucrurile devin puțin mai complicate.
Setarea publicly_queryable
la false
sau rewrite
la false
va împiedica afișarea atât a vizualizării individuale, cât și a celei de arhivă. Nu există niciun parametru în argumentele funcției register_post_type
care să împiedice crearea regulilor de rescriere doar pentru vizualizarea individuală.
https://github.com/WordPress/WordPress/blob/5.2.3/wp-includes/class-wp-post-type.php#L540
Totuși, puteți elimina eticheta de rescriere după înregistrarea tipului de postare, iar acest lucru va lăsa regulile de rescriere pentru vizualizarea arhivei neschimbate, dar va elimina doar regulile de rescriere pentru vizualizarea individuală.
/**
* Înregistrează tipul de postare pentru evenimente
*/
function wpse_128636_register_event_post_type() {
$labels = array(
'name' => __( 'Evenimente' ),
'singular_name' => __( 'Eveniment' ),
'add_new' => __( 'Adaugă nou' ),
'add_new_item' => __( 'Adaugă nou' ),
'edit_item' => __( 'Editează' ),
'new_item' => __( 'Nou' ),
'view_item' => __( 'Vezi' ),
'search_items' => __( 'Caută' ),
'not_found' => __( 'Nu a fost găsit' ),
'not_found_in_trash' => __( 'Nu au fost găsite evenimente în coșul de gunoi' ),
'parent_item_colon' => __( 'Părinte' ),
'menu_name' => __( 'Evenimente' ),
);
$args = array(
'labels' => $labels,
'hierarchical' => false,
'supports' => array( 'title', 'page-attributes' ),
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'show_in_nav_menus' => true,
'publicly_queryable' => true,
'exclude_from_search' => true,
'has_archive' => true,
'rewrite' => array('slug' => 'event'),
'capability_type' => 'post',
);
register_post_type( 'event', $args );
remove_rewrite_tag( '%event%' ); // Această linie va elimina regulile de rescriere pentru vizualizarea individuală a evenimentului
}
add_action( 'init', 'wpse_128636_register_event_post_type' );
Un alt avantaj este că de acum înainte puteți crea pagini WordPress simple folosind structura de legături permanente a tipului de postare pentru evenimente (event/pagina-simpla
), ceea ce poate fi util în site-uri web complexe.
Nu uitați să resetați regulile de rescriere după modificarea codului.

Acesta ar trebui să fie răspunsul acceptat, este scurt, simplu și nu interferează cu paginile de arhivă.

În WordPress 5.9.0
a fost adăugat un nou filtru care permite nu doar dezactivarea postărilor individuale, dar și eliminarea oricăror legături către acestea din ecranele de administrare.
add_filter( 'is_post_type_viewable', function( $is_viewable, $post_type ) {
if ( 'sample_post_type' === $post_type->name ) {
return false;
}
return $is_viewable;
}, 10, 2 );
Postarea individuală nu se va încărca, dar dacă introduceți manual URL-ul, pagina de start se va încărca în loc de o eroare 404. Pentru a afișa o eroare 404 în locul paginii de start, puteți elimina regula de rescriere după ce tipul de postare este înregistrat.
remove_rewrite_tag( '%sample_post_type%' );
După efectuarea acestor modificări, va trebui să resetați regulile de rescriere.
Folosind aceste 2 metode, veți atinge obiectivul fără șabloane suplimentare, redirecționări și legături stricate în administrare.

Soluția mea actuală (în mare parte "soluția de redirecționare") cu o ușoară diferență de implementare.
Aceasta va păstra active paginile de arhivă (has_archive = TRUE
)
Dar vă va permite să activați sau să dezactivați paginile individuale atunci când utilizați register_post_type()
cu x_has_single = TRUE
(parametrul este transmis împreună cu proprietățile obiectului tip post).
add_action( 'init', function() {
$args = [
... // alte variabile
'public' => FALSE,
'publicly_queryable' => TRUE,
'show_ui' => TRUE,
'has_archive' => 'customers',
'rewrite' => [ 'slug' => 'customers', 'with_front' => FALSE ],
'x_has_single' => FALSE,
];
register_post_type( 'customers', $args );
} );
add_action( 'template_redirect', function() {
$post_type = get_post_type() ?: FALSE;
$post_type_obj = get_post_type_object( $post_type );
$has_single = $post_type_obj->x_has_single ?? TRUE;
if ( FALSE === $has_single && $post_type && is_singular( $post_type ) ) {
wp_redirect( get_post_type_archive_link( $post_type ) ?: '/', 301 );
exit;
}
} );
