Cómo forzar un 404 en WordPress

40

Necesito forzar un 404 en algunas publicaciones según las condiciones. Logré hacerlo (aunque no sé si lo hice de la manera correcta) y estoy haciendo que mi 404.phpplantilla se cargue como se esperaba.

Mi código:

function rr_404_my_event() {
  global $post;
  if ( is_singular( 'event' ) && !rr_event_should_be_available( $post->ID ) ) {
    include( get_query_template( '404' ) );
    exit; # so that the normal page isn't loaded after the 404 page
  }
}

add_action( 'template_redirect', 'rr_404_my_event', 1 );

Código 2 de esta pregunta relacionada - mismo problema:

function rr_404_my_event() {
  global $post;
  if ( is_singular( 'event' ) && !rr_event_should_be_available( $post->ID ) ) {
    global $wp_query;
    $wp_query->set_404();
  }
}

add_action( 'wp', 'rr_404_my_event' );

Mi problema:

Aunque se ve bien, obtengo un estado 200 OKsi reviso la pestaña de red. Como es un estado 200, me temo que los motores de búsqueda también pueden indexar esas páginas.

Comportamiento esperado:

Quiero 404 Not Foundque se envíe un estado .

RRikesh
fuente
De las preguntas relacionadas: wordpress.stackexchange.com/questions/73738/… - ¿lo leíste?
fuxia
Sí, todavía tengo un estado 200con eso.
RRikesh

Respuestas:

51

Puede probar la función Wordpress status_header()para agregar el HTTP/1.1 404 Not Foundencabezado;

Entonces su ejemplo de Código 2 sería:

function rr_404_my_event() {
  global $post;
  if ( is_singular( 'event' ) && !rr_event_should_be_available( $post->ID ) ) {
    global $wp_query;
    $wp_query->set_404();
    status_header(404);
  }
}
add_action( 'wp', 'rr_404_my_event' );

Esta función se usa, por ejemplo, en esta parte:

function handle_404() {
    ...cut...
    // Guess it's time to 404.
    $wp_query->set_404();
    status_header( 404 );
    nocache_headers();
    ...cut...
}

de la wpclase en /wp-includes/class-wp.php.

Intente usar este ejemplo modificado del Código 2 además de su template_includecódigo.

Birgire
fuente
El Code 2fragmento que publicaste funciona perfectamente. El set_header()era lo que faltaba.
RRikesh
@birgire al que te refieres para set_header()agregar HTTP/1.1 404 Not Foundpero has usado status_header()en tu código
henrywright
@henrywright parece un error tipográfico allí, actualicé la respuesta, gracias ;-)
birgire
15

Este código funcionó para mí:

add_action ('wp', 'force_404');
función force_404 () {
    global $ wp_query; // $ posts (si es necesario)
    if (is_page ()) {// su condición
        status_header (404);
        nocache_headers ();
        include (get_query_template ('404'));
        morir();
    }
}
golchha21
fuente
Práctico. Estoy buscando parámetros de consulta personalizados, así que no estoy usando la acción, pero es un método muy útil en mi clase de complemento.
John Reid
2
Agregue lo siguiente para corregir el título de la página:global $wp_query; $wp_query->is_404 = true;
developerbmw
2

No recomendaría forzar un 404.

Si le preocupan los motores de búsqueda, ¿por qué no simplemente hacer un meta "sin índice, sin seguimiento" en esas páginas y bloquearlo con robots.txt?

Esta puede ser una mejor manera de bloquear la visualización del contenido.

add_filter( 'template_include', 'nifty_block_content', 99 );

function nifty_block_content( $template ) {
  if ( is_singular( 'event' ) && !rr_event_should_be_available( $post->ID ) ) {
        $template = locate_template( array( 'nifty-block-content.php' ) );
     }
    return $template;
}

Probablemente también podría usar este método para cargar, 404.phppero creo que usar una plantilla de página podría ser una mejor opción.

fuente

Brooke
fuente
Muchas gracias por el enlace, en cambio cambiaré a usar locate_template(). Creo que esa robots.txt.no es una forma garantizada de protegerse de la indexación. Algunos motores de búsqueda aún pueden recoger la página. Quiero que la página se vea como una página 404 normal. Además, las publicaciones se agregarán dinámicamente, editar el robots.txtarchivo agregará más problemas.
RRikesh
1

Mi solución:

add_action( 'wp', 'my_404' );
function my_404() 
{
    if ( is_404() ) 
    {
        header("Status: 404 Not Found");
        $GLOBALS['wp_query']->set_404();
        status_header(404);
        nocache_headers();
        //var_dump(getallheaders()); var_dump(headers_list()); die();
    }
}
T.Todua
fuente
1
La redirección de errores es terrible para el ranking de su página. Simplemente muestre una plantilla en la misma ubicación que la solicitud incorrecta. Lo que sucederá cuando haga eso es que inicialmente configura un 404, y luego la redirección lo altera a 301 o 302, que luego redirige a una página que devuelve 200. Luego, los motores de búsqueda lo indexan como una página válida, que es explícitamente lo que OP dijo que no quería.
mopsyd
0

Los códigos de estado se envían en los encabezados de las solicitudes HTTP. Su función actual está enganchada en un gancho que se llamará demasiado tarde.

Debes intentar conectar tu función rr_404_my_event()a la acción send_headers.

No estoy seguro de si en ese momento es posible verificar la ID de la publicación, pero inténtelo:

add_action( 'send_headers', 'rr_404_my_event' );
function rr_404_my_event() {
    global $post;
    if ( is_singular( 'event' ) && !rr_event_should_be_available( $post->ID ) ) {
        include( get_query_template( '404' ) );
        header('HTTP/1.0 404 Not Found');
        exit; 
    }
}
Marc Dingena
fuente
Corregí algunos errores de sintaxis de sus códigos. Ni siquiera tengo mi plantilla 404 para cargar con eso.
RRikesh
Quizás, en su 404.phppodría cargar una diferente header.php, por ejemplo, <?php get_header('404'); ?>para cargar header-404.php. En ese encabezado, agregaría header('HTTP/1.0 404 Not Found');en la <head>sección.
Marc Dingena
0

Quería compartir la forma en que usé la solución marcada

function fail_safe_for_authors() {
    if ((is_user_logged_in()) && (is_author()) && ($_COOKIE["user_role"] !== "administrator")) {
            global $wp_query;
            $wp_query->set_404();
            status_header(404);
        }
}
add_action("wp", "fail_safe_for_authors");

Hice esto para separar todos los tipos de usuarios del administrador , en este proyecto, solo el administrador puede ver la author.phppágina.

Espero que pueda ayudar a alguien más.

Gendrith
fuente