Jak wymusić 404 na WordPress

40

Muszę wymusić 404 na niektórych postach w zależności od warunków. Udało mi się to zrobić (chociaż nie wiem, czy zrobiłem to we właściwy sposób) i otrzymuję 404.phpszablon do załadowania zgodnie z oczekiwaniami.

Mój kod:

function rr_404_my_event() {
  global $post;
  if ( is_singular( 'event' ) && !rr_event_should_be_available( $post->ID ) ) {
    include( get_query_template( '404' ) );
    exit; # so that the normal page isn't loaded after the 404 page
  }
}

add_action( 'template_redirect', 'rr_404_my_event', 1 );

Kod 2 z tego powiązanego pytania - ten sam 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' );

Mój problem:

Mimo, że wygląda dobrze, dostaję status, 200 OKjeśli sprawdzę kartę sieci. Ponieważ jest to stan 200, obawiam się, że wyszukiwarki mogą również indeksować te strony.

Oczekiwane zachowanie:

Chcę 404 Not Foundwysłać status .

RRikesh
źródło
Z powiązanych pytań: wordpress.stackexchange.com/questions/73738/... - czy przeczytałeś to?
fuxia
Tak, nadal mam 200z tym status .
RRikesh

Odpowiedzi:

50

Możesz spróbować użyć funkcji Wordpress, status_header()aby dodać HTTP/1.1 404 Not Foundnagłówek;

Przykład Twojego kodu 2 to:

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' );

Ta funkcja jest używana na przykład w tej części:

function handle_404() {
    ...cut...
    // Guess it's time to 404.
    $wp_query->set_404();
    status_header( 404 );
    nocache_headers();
    ...cut...
}

z wpklasy w /wp-includes/class-wp.php.

Spróbuj więc użyć tego zmodyfikowanego przykładu Code 2 oprócz template_includekodu.

birgire
źródło
Code 2Snippet ty pisał działa idealnie. Tego set_header()brakowało.
RRikesh
@birgire, do którego chcesz się set_header()dodać, HTTP/1.1 404 Not Foundale użyłeś status_header()w swoim kodzie?
henrywright
@henrywright wygląda jak literówka, zaktualizowałem odpowiedź, dzięki ;-)
birgire
15

Ten kod działał dla mnie:

działanie dodatkowe („wp”, „force_404”);
funkcja force_404 () {
    globalny $ wp_query; // $ posts (jeśli wymagane)
    if (is_page ()) {// twój warunek
        status_header (404);
        nocache_headers ();
        include (get_query_template ('404'));
        umierać();
    }
}
golchha21
źródło
Poręczny. Sprawdzam niestandardowe parametry zapytania, więc nie korzystam z akcji, ale jest to bardzo przydatna metoda w mojej klasie wtyczek.
John Reid
2
Dodaj następujące informacje, aby naprawić tytuł strony:global $wp_query; $wp_query->is_404 = true;
developerbmw
2

Nie poleciłbym forsowania 404.

Jeśli martwisz się o wyszukiwarki, dlaczego po prostu nie utworzysz meta „bez indeksu, bez śledzenia” na tych stronach i zablokujesz go za pomocą pliku robots.txt?

Może to być lepszy sposób na zablokowanie przeglądania zawartości

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;
}

Prawdopodobnie możesz także użyć tej metody do załadowania, 404.phpale uważam, że lepszym rozwiązaniem może być użycie szablonu strony.

źródło

Brooke.
źródło
Wielkie dzięki za link, przejdę na używanie locate_template()zamiast tego. Myślę, że robots.txt.nie jest to gwarantowany sposób ochrony przed indeksacją. Niektóre wyszukiwarki mogą nadal pobierać stronę. Chcę, aby strona wyglądała jak normalna strona 404. Również posty będą dodawane dynamicznie, edycja robots.txtpliku spowoduje więcej problemów.
RRikesh
1

Moje rozwiązanie:

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();
    }
}
T.Todua
źródło
1
Przekierowywanie błędów jest straszne dla twojego rankingu strony. Po prostu pokaż szablon w tej samej lokalizacji, co złe żądanie. Gdy to zrobisz, najpierw ustaw 404, a następnie przekierowanie zmienia je na 301 lub 302, które następnie przekierowują na stronę, która zwraca 200. Następnie wyszukiwarki indeksują je jako prawidłową stronę, która jest wyraźnie tym, co OP powiedział, że nie chce.
mopsyd
0

Kody stanu są wysyłane w nagłówkach żądań HTTP. Twoja bieżąca funkcja jest zaczepiona w haczyku, który zostanie wywołany zbyt późno.

Powinieneś spróbować podłączyć swoją funkcję rr_404_my_event()do działania send_headers.

Nie jestem pewien, czy w tym momencie można nawet sprawdzić identyfikator postu, ale spróbuj:

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; 
    }
}
Marc Dingena
źródło
Poprawiłem niektóre błędy składniowe z twoich kodów. Nie mogę nawet załadować mojego szablonu 404.
RRikesh
Być może 404.phpmożesz załadować inny header.php, np . <?php get_header('404'); ?>Załadować header-404.php. W tym nagłówku dodajesz header('HTTP/1.0 404 Not Found');w <head>sekcji.
Marc Dingena
0

Chciałem się podzielić tym, w jaki sposób korzystałem z oznaczonego rozwiązania

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");

Zrobiłem to, aby oddzielić wszystkie typy użytkowników od administratora , w tym projekcie tylko administrator może zobaczyć author.phpstronę.

Mam nadzieję, że to może pomóc komuś innemu.

Gendrith
źródło