Come forzare un errore 404 in WordPress
Ho bisogno di forzare un errore 404 su alcuni post in base a determinate condizioni. Sono riuscito a farlo (anche se non sono sicuro di averlo fatto nel modo giusto) e il mio template 404.php
viene caricato come previsto.
Il mio codice:
function rr_404_my_event() {
global $post;
if ( is_singular( 'event' ) && !rr_event_should_be_available( $post->ID ) ) {
include( get_query_template( '404' ) );
exit; # termina l'esecuzione così che la pagina normale non venga caricata dopo la 404
}
}
add_action( 'template_redirect', 'rr_404_my_event', 1 );
Codice 2 da questa domanda correlata - stesso 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' );
Il mio problema:
Anche se sembra funzionare, ottengo uno status 200 OK
se controllo la scheda network. Dato che restituisce status 200
, ho paura che i motori di ricerca possano indicizzare quelle pagine.
Comportamento atteso:
Voglio che venga inviato uno status 404 Not Found
.

Potresti provare la funzione WordPress status_header()
per aggiungere l'header HTTP/1.1 404 Not Found
;
Quindi il tuo esempio Codice 2 diventerebbe:
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' );
Questa funzione viene utilizzata ad esempio in questa parte:
function handle_404() {
...tagliato...
// Sembra sia il momento di mostrare un 404.
$wp_query->set_404();
status_header( 404 );
nocache_headers();
...tagliato...
}
della classe wp
in /wp-includes/class-wp.php
.
Quindi prova a utilizzare questo esempio modificato del Codice 2 in aggiunta al tuo codice template_include
.

Lo snippet Code 2
che hai postato funziona perfettamente. Manca proprio il set_header()
.

@birgire ti riferisci a set_header()
per aggiungere HTTP/1.1 404 Not Found
ma hai usato status_header()
nel tuo codice?

Pratico. Sto controllando i parametri di query personalizzati quindi non sto usando l'azione, ma costituisce un metodo molto utile nella mia classe del plugin.

Il modo più robusto che ho trovato per ottenere questo risultato è utilizzare il filtro template_include
, in questo modo:
function wpse91900_force_404(string $template): string {
if ($some_condition) {
global $wp_query;
$wp_query->set_404(); // Imposta la query come pagina 404
status_header(404); // Imposta l'header HTTP a 404
nocache_headers(); // Disabilita la cache per questa pagina
$template = get_404_template(); // Ottiene il template per la pagina 404
}
return $template;
}
add_filter("template_include", "wpse91900_force_404");

Non consiglierei di forzare un errore 404.
Se sei preoccupato per i motori di ricerca, perché non usare semplicemente un meta tag "no-index,no-follow" su quelle pagine e bloccarle con robots.txt?
Questo potrebbe essere un modo migliore per impedire la visualizzazione del contenuto
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;
}
Probabilmente potresti usare questo metodo anche per caricare 404.php
ma credo che usare un template di pagina potrebbe essere un'opzione migliore.

Grazie mille per il link, passerò a usare locate_template()
invece. Penso che robots.txt.
non sia un modo garantito per proteggere dall'indicizzazione. Alcuni motori di ricerca potrebbero comunque rilevare la pagina. Voglio che la pagina appaia come una normale pagina 404. Inoltre i post verranno aggiunti dinamicamente, modificare il file robots.txt
creerebbe solo più problemi.

Volevo condividere il modo in cui ho utilizzato la soluzione indicata.
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");
Ho fatto questo per separare tutti i tipi di utenti dall'amministratore, in questo progetto solo l'admin può vedere la pagina author.php
.
Spero che possa essere utile a qualcun altro.

Il reindirizzamento in caso di errori è pessimo per il posizionamento della tua pagina. Mostra semplicemente un template nella stessa posizione della richiesta non valida. Ciò che succederà quando lo farai è che inizialmente imposterai un 404, e poi il reindirizzamento lo modificherà in un 301 o 302, che a sua volta reindirizzerà a una pagina che restituirà un 200. Questo verrà poi indicizzato dai motori di ricerca come una pagina valida, che è esattamente ciò che OP ha detto di non volere.

I codici di stato vengono inviati negli header delle richieste HTTP. La tua funzione attuale è agganciata a un hook che verrà chiamato troppo tardi.
Dovresti provare ad agganciare la tua funzione rr_404_my_event()
all'azione send_headers
.
Non sono sicuro che a quel punto sia ancora possibile verificare l'ID del post, ma prova questo:
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;
}
}

Ho corretto alcuni errori di sintassi dai tuoi codici. Non riesco nemmeno a far caricare il mio template 404 con quello.

Forse, nel tuo 404.php
potresti caricare un diverso header.php
, ad esempio <?php get_header('404'); ?>
per caricare header-404.php
. In quell'header, aggiungeresti header('HTTP/1.0 404 Not Found');
nella sezione <head>
.
