¿Cómo deshabilitar la vista individual para un tipo de entrada personalizada?
Dado este tipo de entrada personalizada:
register_post_type(
'sample_post_type',
[
'labels' => [
'name' => _x('Entradas de Ejemplo', 'nombre general del tipo de entrada'),
'singular_name' => _x('Entrada de Ejemplo', 'nombre singular del tipo de entrada'),
],
'public' => true,
'show_in_nav_menus' => false,
'exclude_from_search' => true,
]
);
¿Cómo puedo deshabilitar la vista de entrada individual para este tipo de entrada en particular? Mostrar un simple 404 está bien, o redirigir a la página de inicio. Como esto es un plugin, no puedo crear un archivo single-sample_post_type.php
para configurar una página vacía.

Esto parece la respuesta para evitar que tu CPT cree páginas web reales mientras sigue creando todas las referencias en la base de datos.

Para deshabilitar la vista individual de un CPT (Tipo de Entrada Personalizado) puedes redirigir a los usuarios a una URL específica o deshabilitarla durante el registro del propio CPT.
MÉTODO 1:
Redirigir la vista individual del CPT a una URL personalizada, mientras la página de archivo permanece accesible públicamente.
Puedes usar el hook template_redirect
para redirigir al usuario. Puedes usar cualquier URL en lugar de home_url()
y el código de error deseado como segundo argumento.
<?php
add_action( 'template_redirect', 'wpse_128636_redirect_post' );
function wpse_128636_redirect_post() {
if ( is_singular( 'sample_post_type' ) ) :
wp_redirect( home_url(), 301 );
exit;
endif;
}
?>
MÉTODO 2:
Deshabilitar completamente las páginas individuales y de archivo desde el front-end; Funciona solo para Tipos de Entradas Personalizados.
Un enfoque alternativo es establecer publicly_queryable
en false al registrar la entrada personalizada.
'publicly_queryable' => false
Esto oculta tanto la página individual como la de archivo para el CPT, y solo puede usarse para entradas personalizadas.
Aunque el archivo y la vista individual estén ocultos, aún puedes agregar una plantilla de página o un bloque personalizado para listar las entradas si es necesario.

Una buena solución. Encontré que fue útil realizar esta redirección solo para usuarios no autenticados, verificando si get_current_user_id()
devuelve 0.

¿por qué no usar solo is_singular('post-type-slug')
en la condición if()
en lugar de 2 condiciones?

@AkashK. Sí, eso también podría funcionar, no estaba al tanto de esa función.

la sugerencia remove_rewrite_tag( '%post-type-slug%' ); es una buena solución

Probé todas las soluciones mencionadas anteriormente y la solución real es más simple que cualquier redirección sugerida.
Para que el archivo sea accesible y liste los elementos, y que las entradas individuales no sean accesibles y redirijan automáticamente a un error 404, configura:
'query_var' => false
al registrar tu CPT (Tipo de Contenido Personalizado). Si configuras publicly_queryable
como false, tus archivos serán redirigidos a la página de inicio; ninguna otra combinación funcionará. Simplemente establece query_var
como false y eso es todo.
Aquí está el CPT completo: https://gist.github.com/danyj/bfd038d3c8d578548c4d700bd0a7942a
ver línea 50 https://gist.github.com/danyj/bfd038d3c8d578548c4d700bd0a7942a#file-thz_cpt_items_single_view_redirect-php-L50
como se indica aquí:
https://codex.wordpress.org/Function_Reference/register_post_type
Nota: Si query_var está vacío, es null o un booleano FALSE, WordPress intentará interpretarlo (4.2.2) y las vistas previas/visualizaciones de tu contenido personalizado devolverán errores 404.

Se siente un poco como un truco pero parece funcionar. Ojalá agregaran una propiedad dedicada has_single junto con la propiedad existente has_archive.

Hola, intenté hacer lo mismo pero no funcionó. A pesar de agregar el query_var
a false
, todavía puedo visitar los enlaces de páginas individuales. ¿Puedes ayudarme?

@iSaumya intenta actualizar tus permalinks (ve a la página de permalinks y guarda nuevamente) o usa el comando wp-cli wp rewrite flush && wp cache flush

Ya no funciona (agosto 2022). La nota sobre que las vistas individuales fueron eliminadas tampoco existe más en la documentación.

@blorf la nota todavía está en los documentos - está listada bajo publicly_queryable

Esto funciona para mí, tengo Elementor con JetEngine y estoy configurando el tipo de publicación con public
, publicly_queryable
y has_archive
establecidos en true, con query_var
establecido en false. Mis archivos están funcionando y mis entradas individuales hacen 301 a la página de inicio.

Una forma más sencilla de hacerlo puede ser pasando los siguientes argumentos al registrar el Custom Post Type
register_post_type('sample_post_type',array(
'labels' => array(
'name' => _x('Publicaciones de Ejemplo', 'nombre general del tipo de post'),
'singular_name' => _x('Publicación de Ejemplo', 'nombre singular del tipo de post')
),
'public' => true,
'exclude_from_search' => true,
'show_in_admin_bar' => false,
'show_in_nav_menus' => false,
'publicly_queryable' => false,
'query_var' => false
));

En realidad necesitarías que publically_querable
sea verdadero para que funcionen los Archivos de Tipo de Entrada.

Esto no funciona para mí. Simplemente redirige de vuelta a la página de inicio cuando intento acceder al archivo

Uno. Desde tu archivo de funciones.
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;
}
}
Dos. Desde tu archivo single.cpt.php:
<?php wp_redirect( home_url() ); exit; ?>

Me gustó la segunda opción. Pero necesito saber si hay alguna desventaja con esta segunda opción.

@user2584538 Si no tienes un archivo personalizado single-cpt_name.php
no podrías hacerlo. Si pones la función en un archivo simple de plugin, podrías activar/desactivar sin editar ningún archivo.

Trabajando a partir de la muy buena respuesta de Sven, reescribí su función para facilitar la adición de múltiples tipos de publicación utilizando in_array()
en la declaración if y luego redirigiendo a la página de archivo en lugar de a la página de inicio.
(por cierto, creo que la configuración query_var
y/o publically_queryable
en false deshabilitará no solo las vistas individuales, sino también la vista de archivo nativa, anulando 'has_archive' => true
. En ese caso, aún puedes configurar un WP_query personalizado y crear tu propia página de archivo, en una plantilla, pero la consulta principal ya no lo hará, ¿verdad?)
function fq_disable_single_cpt_views() {
$queried_post_type = get_query_var('post_type');
$cpts_without_single_views = array( 'mi-tipo-de-publicacion', 'mi-otro-tipo-de-publicacion' );
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' );

esta fue una buena idea, pero no funciona si cambias tu redirección para los CPTs

Cambié tu línea wp_redirect a wp_redirect( get_post_type_archive_link( $queried_post_type ), 301 );
¡funciona perfectamente!

En caso de que desees deshabilitar completamente la vista individual de un tipo de publicación personalizado en el frontend pero aún así poder mostrar la página de archivo, las cosas se complican un poco.
Establecer publicly_queryable
en false
o rewrite
en false
evitará que se muestren tanto la vista individual como la de archivo. No hay una bandera en los argumentos de la función register_post_type
para prevenir la creación de reglas de reescritura solo para la vista individual.
https://github.com/WordPress/WordPress/blob/5.2.3/wp-includes/class-wp-post-type.php#L540
Sin embargo, puedes eliminar la etiqueta de reescritura después de registrar tu tipo de publicación y esto dejará intactas las reglas de reescritura de la vista de archivo, pero eliminará solo las reglas de reescritura de la vista individual.
/**
* Registrar el tipo de publicación 'event'
*/
function wpse_128636_register_event_post_type() {
$labels = array(
'name' => __( 'Eventos' ),
'singular_name' => __( 'Evento' ),
'add_new' => __( 'Añadir nuevo' ),
'add_new_item' => __( 'Añadir nuevo' ),
'edit_item' => __( 'Editar' ),
'new_item' => __( 'Nuevo' ),
'view_item' => __( 'Ver' ),
'search_items' => __( 'Buscar' ),
'not_found' => __( 'No encontrado' ),
'not_found_in_trash' => __( 'No se encontraron Eventos en la papelera' ),
'parent_item_colon' => __( 'Padre' ),
'menu_name' => __( 'Eventos' ),
);
$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%' ); // Esta línea eliminará las reglas de reescritura para la vista individual
}
add_action( 'init', 'wpse_128636_register_event_post_type' );
Otro beneficio es que a partir de ahora puedes crear páginas simples de WordPress utilizando la estructura de enlaces permanentes del tipo de publicación 'event' (event/pagina-simple
), lo que puede ser útil en sitios web complejos.
Recuerda limpiar las reglas de reescritura después de modificar el código.

Esta debería ser la respuesta aceptada, es corta, simple y no afecta las páginas de archivo.

En WordPress 5.9.0
se añadió un nuevo filtro que permite no solo deshabilitar el single sino también eliminar cualquier enlace hacia él en las pantallas de administración.
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 );
El single no cargará, pero si introduces la URL manualmente, se cargará la página de inicio en lugar de un 404. Para mostrar un 404 en vez de la página de inicio, puedes eliminar la regla de rewrite después de registrar el tipo de contenido.
remove_rewrite_tag( '%sample_post_type%' );
Después de realizar estos cambios, necesitarás limpiar las reglas de rewrite.
Usando estos 2 métodos lograrás el objetivo sin necesidad de plantillas adicionales, redirecciones o enlaces rotos en el admin.

Mi solución actual (principalmente "la solución de redirección") con una ligera diferencia en la implementación.
Esto mantendrá habilitadas las páginas de archivo (has_archive = TRUE
)
Pero permitirá habilitar o deshabilitar las páginas individuales cuando uses register_post_type()
con x_has_single = TRUE
(el parámetro se pasa junto con las propiedades del objeto del tipo de contenido).
add_action( 'init', function() {
$args = [
... // otras variables
'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;
}
} );
