Cum să forțezi o eroare 404 în WordPress
Am nevoie să forțez o eroare 404 pentru unele postări bazate pe anumite condiții. Am reușit să fac acest lucru (deși nu sunt sigur dacă am făcut-o corect) și template-ul meu 404.php
se încarcă așa cum mă așteptam.
Codul meu:
function rr_404_my_event() {
global $post;
if ( is_singular( 'event' ) && !rr_event_should_be_available( $post->ID ) ) {
include( get_query_template( '404' ) );
exit; # pentru a preveni încărcarea paginii normale după pagina 404
}
}
add_action( 'template_redirect', 'rr_404_my_event', 1 );
Codul 2 din această întrebare înrudită - aceeași problemă:
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' );
Problema mea:
Deși pare să funcționeze, primesc un status 200 OK
când verific în tab-ul Network. Deoarece este un status 200
, mă tem că motoarele de căutare ar putea indexa aceste pagini.
Comportamentul așteptat:
Vreau ca serverul să returneze un status 404 Not Found
.

Ai putea încerca funcția WordPress status_header()
pentru a adăuga antetul HTTP/1.1 404 Not Found
;
Deci exemplul tău Code 2 ar arăta astfel:
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' );
Această funcție este folosită de exemplu în această porțiune:
function handle_404() {
...tăiat...
// Presupunem că e momentul pentru 404.
$wp_query->set_404();
status_header( 404 );
nocache_headers();
...tăiat...
}
din clasa wp
din fișierul /wp-includes/class-wp.php
.
Deci încearcă să folosești acest exemplu modificat Code 2 în plus față de codul tău template_include
.

Fragmentul de cod Code 2
pe care l-ai postat funcționează perfect. set_header()
era ceea ce lipsea.

@birgire te referi la set_header()
pentru a adăuga HTTP/1.1 404 Not Found
dar ai folosit status_header()
în codul tău?

Folositor. Verific parametri personalizați în interogare, așa că nu folosesc acțiunea, dar este o metodă foarte utilă în clasa mea de plugin.

Cea mai robustă metodă pe care am găsit-o pentru a realiza acest lucru este să o faci în filtrul template_include
, astfel:
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");

Nu aș recomanda forțarea unei erori 404.
Dacă ești îngrijorat de motoarele de căutare, de ce nu adaugi pur și simplu un meta tag "no-index,no-follow" pe acele pagini și le blochezi cu robots.txt?
Aceasta ar putea fi o metodă mai bună de a bloca vizualizarea conținutului
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;
}
Ai putea probabil folosi și această metodă pentru a încărca 404.php
dar cred că utilizarea unui template de pagină ar fi o opțiune mai bună.

Mulțumesc mult pentru link, voi trece la utilizarea locate_template()
în loc. Cred că robots.txt
nu este o metodă garantată pentru protecția împotriva indexării. Unele motoare de căutare ar putea totuși prelua pagina. Vreau ca pagina să arate ca o pagină normală de 404. De asemenea, postările vor fi adăugate dinamic, iar editarea fișierului robots.txt
va aduce probleme suplimentare.

Am vrut să împărtășesc modul în care am folosit soluția marcată
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");
Am făcut asta pentru a separa toate tipurile de utilizatori de administrator, în acest proiect, doar adminul poate vedea pagina author.php
.
Sper că ar putea ajuta pe altcineva.

Redirecționarea în caz de erori este dezastruoasă pentru poziționarea paginii tale. Pur și simplu afișează un șablon în aceeași locație ca și cererea incorectă. Ceea ce se va întâmpla atunci când faci asta este că inițial setezi un cod 404, iar apoi redirecționarea îl schimbă într-un 301 sau 302, care apoi redirecționează către o pagină care returnează un 200. Aceasta va fi apoi indexată de motoarele de căutare ca o pagină validă, ceea ce este exact ceea ce OP a spus că nu dorește.

Codurile de stare sunt trimise în anteturile cererilor HTTP. Funcția ta curentă este conectată la un cârlig care va fi apelat prea târziu.
Ar trebui să încerci să conectezi funcția ta rr_404_my_event()
la acțiunea send_headers
.
Nu sunt sigur dacă în acel moment este posibil să verifici ID-ul postării, dar încearcă asta:
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;
}
}

Am corectat câteva erori de sintaxă din codurile tale. Nici măcar nu reușesc să încarc șablonul meu 404 cu asta.

Poate că în 404.php
ai putea încărca un header.php
diferit, de exemplu <?php get_header('404'); ?>
pentru a încărca header-404.php
. În acel header, ai adăuga header('HTTP/1.0 404 Not Found');
în secțiunea <head>
.
