El código de estado HTTP 404 indica que el recurso solicitado no se ha encontrado en el servidor. Se ha popularizado la idea de que es un error que hay que solucionar a toda costa, pero nada más lejos de la realidad, si una URL apunta a un recurso inexistente tiene y debe devolver el código de estado 404, cualquier otra cosa estaría mal (excepto algunas excepciones) y podría incluso ser contraproducente desde un punto de vista SEO.

Normalmente los errores 404 en WordPress son generados de forma automática pero en algunos casos puede ser necesario que los forcemos. La función específica de WordPress para generar el código de estado HTTP es status_header(). Basta con especificar el código de estado que deseamos y listo, en el caso del error 404:

status_header( 404 );

No lo he probado a conciencia pero lo más adecuado, en general y si de verdad queremos forzar el estado 404, parece ser utilizar status_header() en el action template_redirect. Después ya ha podido salir información, ya no podríamos modificar las cabeceras y generaríamos error «Cannot modify header information – headers already sent«. Si la utilizamos antes las cabeceras pueden ser modificadas de nuevo posteriormente y se perdería nuestra intención de enviar la cabecera de estado 404.

Por ejemplo:

add_action( 'template_redirect', function() {

    status_header( 404 );

} );

Con el código anterior, si visitamos una URL real y existente, por ejemplo de un post, podríamos ver el post aunque si comprobamos las cabeceras podremos ver el error 404. Si además de la cabecera 404 queremos también que WordPress cargue la plantilla 404.php, tenemos que hacer algo más. Tenemos que decirle a WordPress que el query principal es un 404. Por ejemplo, lo podemos hacer en el action parse_query:

add_action( 'parse_query', 'cyb_generate_404' );
function cyb_generate_404( $query ) {

    // El query principal no ha encontrado nada
    // Se utilizará la plantilla 404.php del tema
    // pero no afecta a las cabeceras
    $query->set_404();

    // Se establece la cabecera de estado
    // Si no se establece WordPress carga la plantilla 404.php
    // Pero puede que con código de estado diferente a 404
    status_header( 404 );

}