Cómo forzar un error 404 en WordPress

22 mar 2013, 08:53:33
Vistas: 92K
Votos: 53

Necesito forzar un error 404 en algunas publicaciones basado en condiciones. Logré hacerlo (aunque no sé si fue la forma correcta) y estoy cargando mi plantilla 404.php como 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; # para que la página normal no se cargue después de la página 404
  }
}

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 parece funcionar, obtengo un estado 200 OK si reviso la pestaña de red. Como es un estado 200, me preocupa que los motores de búsqueda puedan indexar esas páginas.

Comportamiento esperado:

Quiero que se envíe un estado 404 No encontrado.

2
Comentarios

De las preguntas relacionadas: http://wordpress.stackexchange.com/questions/73738/how-do-i-programmatically-generate-a-404 – ¿has leído eso?

fuxia fuxia
22 mar 2013 11:34:50

Sí, aún obtengo un estado 200 con eso.

RRikesh RRikesh
22 mar 2013 11:40:47
Todas las respuestas a la pregunta 7
3
78

Podrías probar la función de Wordpress status_header() para agregar el encabezado HTTP/1.1 404 No Encontrado;

Entonces tu ejemplo Código 2 quedarí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 utiliza por ejemplo en esta parte:

function handle_404() {
    ...cut...
    // Supongo que es momento de devolver 404.
    $wp_query->set_404();
    status_header( 404 );
    nocache_headers();
    ...cut...
}

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

Así que prueba usando este ejemplo modificado de Código 2 además de tu código con template_include.

24 mar 2013 20:17:28
Comentarios

El fragmento de Code 2 que publicaste funciona perfectamente. El set_header() era lo que faltaba.

RRikesh RRikesh
25 mar 2013 07:11:42

@birgire te refieres a set_header() para agregar HTTP/1.1 404 Not Found pero has usado status_header() en tu código?

henrywright henrywright
8 sept 2014 16:08:48

@henrywright parece que hubo un error tipográfico allí, actualicé la respuesta, gracias ;-)

birgire birgire
8 sept 2014 16:45:24
2
23

Este código funcionó para mí:


add_action( 'wp', 'force_404' );
function force_404() {
    global $wp_query; //$posts (si es requerido)
    if(is_page()){ // tu condición
        status_header( 404 );
        nocache_headers();
        include( get_query_template( '404' ) );
        die();
    }
}
24 mar 2013 20:42:04
Comentarios

Útil. Estoy verificando parámetros de consulta personalizados, así que no estoy usando la acción, pero resulta un método muy útil en mi clase de plugin.

John Reid John Reid
17 oct 2014 11:26:56

Agrega lo siguiente para corregir el título de la página: global $wp_query; $wp_query->is_404 = true;

brettwhiteman brettwhiteman
25 feb 2016 00:18:54
0

La forma más robusta que he encontrado para lograr esto es hacerlo en el filtro template_include, de la siguiente manera:

function wpse91900_force_404(string $template): string {
    if ($some_condition) {
        global $wp_query;

        $wp_query->set_404();
        status_header(404);
        nocache_headers();

        $template = get_404_template();
    }

    return $template;
}
add_filter("template_include", "wpse91900_force_404");
1 feb 2022 17:33:22
1

No recomendaría forzar un error 404.

Si te preocupan los motores de búsqueda, ¿por qué no simplemente agregas una metaetiqueta "no-index,no-follow" a esas páginas y las bloqueas con robots.txt?

Esta podría ser una mejor manera de bloquear el contenido para que no se vea

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ías usar este método para cargar 404.php pero siento que usar una plantilla de página podría ser una mejor opción.

fuente

22 mar 2013 10:47:21
Comentarios

Muchas gracias por el enlace, voy a cambiar a usar locate_template() en su lugar. Creo que robots.txt. no es una forma garantizada de proteger contra la indexación. Algunos motores de búsqueda podrían seguir recogiendo la página. Quiero que la página parezca una página 404 normal. Además, las publicaciones se van a añadir dinámicamente, editar el archivo robots.txt añadirá más problemas.

RRikesh RRikesh
22 mar 2013 11:23:15
0

Quería compartir la forma en que utilicé 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 admin puede ver la página author.php.

Espero que pueda ayudar a alguien más.

4 oct 2019 21:20:53
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();
    }
}
21 jul 2014 15:24:48
Comentarios

Redirigir en caso de errores es terrible para el ranking de tu página. Simplemente muestra una plantilla en la misma ubicación que la solicitud incorrecta. Lo que sucederá cuando hagas eso es que inicialmente configurarás un 404, y luego la redirección lo cambiará a un 301 o 302, que luego redirigirá a una página que devuelve un 200. Eso luego es indexado por los motores de búsqueda como una página válida, que es exactamente lo que OP dijo que no quería.

mopsyd mopsyd
15 mar 2018 03:43:12
3

Los códigos de estado se envían en las cabeceras de las peticiones HTTP. Tu función actual está enganchada a un hook que se llamará demasiado tarde.

Deberías intentar enganchar tu función rr_404_my_event() a la acción send_headers.

No estoy seguro de si en ese momento es posible verificar el ID de la entrada, pero prueba esto:

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; 
    }
}
22 mar 2013 12:42:35
Comentarios

Corregí algunos errores de sintaxis en tus códigos. Ni siquiera logro que mi plantilla 404 se cargue con eso.

RRikesh RRikesh
22 mar 2013 12:48:41

Quizás, en tu 404.php podrías cargar un header.php diferente, por ejemplo <?php get_header('404'); ?> para cargar header-404.php. En ese encabezado, agregarías header('HTTP/1.0 404 Not Found'); en la sección <head>.

Marc Dingena Marc Dingena
22 mar 2013 13:07:07

@MarcDingena Supongo que debes colocar la línea header() antes de la que muestra los contenidos de la plantilla, de lo contrario verás la página de plantilla correcta pero el código de estado HTTP real seguirá siendo 200.

David Wolf David Wolf
26 feb 2022 22:28:16