Come forzare un errore 404 in WordPress

22 mar 2013, 08:53:33
Visualizzazioni: 92K
Voti: 53

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.

2
Commenti

Dalle domande correlate: http://wordpress.stackexchange.com/questions/73738/how-do-i-programmatically-generate-a-404 – l'hai letta?

fuxia fuxia
22 mar 2013 11:34:50

Sì, ottengo ancora uno status 200 con quello.

RRikesh RRikesh
22 mar 2013 11:40:47
Tutte le risposte alla domanda 7
3
78

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.

24 mar 2013 20:17:28
Commenti

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

RRikesh RRikesh
25 mar 2013 07:11:42

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

henrywright henrywright
8 set 2014 16:08:48

@henrywright sembra un errore di battitura, ho aggiornato la risposta, grazie ;-)

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

Questo codice ha funzionato per me:


add_action( 'wp', 'force_404' );
function force_404() {
    global $wp_query; //$posts (se necessario)
    if(is_page()){ // tua condizione
        status_header( 404 );
        nocache_headers();
        include( get_query_template( '404' ) );
        die();
    }
}
24 mar 2013 20:42:04
Commenti

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.

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

Aggiungi quanto segue per sistemare il titolo della pagina: global $wp_query; $wp_query->is_404 = true;

brettwhiteman brettwhiteman
25 feb 2016 00:18:54
0

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");
1 feb 2022 17:33:22
1

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.

fonte

22 mar 2013 10:47:21
Commenti

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.

RRikesh RRikesh
22 mar 2013 11:23:15
0

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.

4 ott 2019 21:20:53
1

La mia soluzione:

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 lug 2014 15:24:48
Commenti

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.

mopsyd mopsyd
15 mar 2018 03:43:12
3

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

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

RRikesh RRikesh
22 mar 2013 12:48:41

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>.

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

@MarcDingena Penso che tu debba mettere la riga header() sopra quella in cui outputti i contenuti del template, altrimenti vedrai la pagina del template corretta, ma il vero codice di stato HTTP sarà ancora 200.

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