Как заставить 404 на WordPress

40

Мне нужно заставить 404 на некоторых должностях в зависимости от условий. Мне удалось это сделать (хотя я не знаю, правильно ли я это сделал), и я получаю свой 404.phpшаблон для загрузки, как ожидалось.

Мой код:

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

Код 2 из этого смежного вопроса - та же проблема:

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

Моя проблема:

Хотя это выглядит хорошо, я получаю статус, 200 OKесли я проверяю вкладку сети. Поскольку это статус 200, я боюсь, что поисковые системы тоже могут проиндексировать эти страницы.

Ожидаемое поведение:

Я хочу, чтобы статус 404 Not Foundбыл отправлен.

RRikesh
источник
Из связанных с этим вопросов: wordpress.stackexchange.com/questions/73738/… - Вы это читали?
fuxia
Да, я все еще получаю статус 200с этим.
RRikesh

Ответы:

51

Вы можете попробовать функцию Wordpress, status_header()чтобы добавить HTTP/1.1 404 Not Foundзаголовок;

Таким образом, ваш пример кода 2 будет:

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

Эта функция, например, используется в этой части:

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

из wpкласса в /wp-includes/class-wp.php.

Поэтому попробуйте использовать этот модифицированный пример Code 2 в дополнение к вашему template_includeкоду.

birgire
источник
Размещенный Code 2вами фрагмент отлично работает. Это set_header()было то, чего не хватало.
RRikesh
@birgire вы ссылаетесь, чтобы set_header()добавить, HTTP/1.1 404 Not Foundно использовали status_header()в своем коде?
Генрирайт
@henrywright там похоже на опечатку, я обновил ответ, спасибо ;-)
birgire
15

Этот код работал для меня:

add_action ('wp', 'force_404');
function force_404 () {
    глобальный $ wp_query; // $ posts (если требуется)
    if (is_page ()) {// ваше состояние
        status_header (404);
        nocache_headers ();
        include (get_query_template ('404'));
        умереть();
    }
}
golchha21
источник
Handy. Я проверяю пользовательские параметры запроса, поэтому я не использую действие, но оно делает его очень полезным методом в моем классе плагинов.
Джон Рейд
2
Добавьте следующее, чтобы исправить заголовок страницы:global $wp_query; $wp_query->is_404 = true;
developerbmw
2

Я бы не рекомендовал форсировать 404.

Если вы беспокоитесь о поисковых системах, почему бы просто не создать мета «без индекса, без подписки» на этих страницах и заблокировать ее с помощью robots.txt?

Это может быть лучшим способом заблокировать просмотр контента

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

Возможно, вы также можете использовать этот метод для загрузки, 404.phpно я чувствую, что использование шаблона страницы может быть лучшим вариантом.

источник

Брук.
источник
Большое спасибо за ссылку, я переключусь на использование locate_template()вместо этого. Я думаю, что robots.txt.это не гарантированный способ защиты от индексации. Некоторые поисковые системы могут все еще поднять страницу. Я хочу, чтобы страница выглядела как обычная страница 404. Также посты будут добавляться динамически, редактирование robots.txtфайла добавит больше проблем.
RRikesh
1

Мое решение:

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
источник
1
Перенаправление на ошибки ужасно для вашего рейтинга страницы. Просто покажите шаблон в том же месте, что и неверный запрос. Что произойдет, когда вы сделаете это, вы сначала установите 404, а затем редирект изменяет его на 301 или 302, который затем перенаправляет на страницу, которая возвращает 200. Это затем индексируется поисковыми системами как действительная страница, которая явно то, что ОП сказал, что он не хочет.
Мопсид
0

Коды состояния отправляются в заголовках HTTP-запросов. Ваша текущая функция подключена к ловушке, которая будет вызвана слишком поздно.

Вы должны попытаться подключить свою функцию rr_404_my_event()к действию send_headers.

Я не уверен, что в этот момент можно даже проверить идентификатор сообщения, но попробуйте:

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; 
    }
}
Марк Дингена
источник
Я исправил некоторые синтаксические ошибки из ваших кодов. Я даже не получаю свой шаблон 404 для загрузки с этим.
RRikesh
Возможно, у вас 404.phpвы можете загрузить другое header.php, например, <?php get_header('404'); ?>загрузить header-404.php. В этом заголовке вы добавите header('HTTP/1.0 404 Not Found');в <head>раздел.
Марк Дингена
0

Я хотел бы поделиться тем, как я использовал отмеченное решение

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

Я сделал это, чтобы отделить все типы пользователей от администратора , в этом проекте только администратор может видеть author.phpстраницу.

Я надеюсь, что это может помочь кому-то еще.

Gendrith
источник