Как принудительно вызвать ошибку 404 в WordPress

22 мар. 2013 г., 08:53:33
Просмотры: 92K
Голосов: 53

Мне нужно принудительно вызывать 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; # чтобы обычная страница не загружалась после страницы 404
  }
}

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.

2
Комментарии

Из похожих вопросов: http://wordpress.stackexchange.com/questions/73738/how-do-i-programmatically-generate-a-404 – вы это читали?

fuxia fuxia
22 мар. 2013 г. 11:34:50

Да, но я всё равно получаю статус 200 с этим.

RRikesh RRikesh
22 мар. 2013 г. 11:40:47
Все ответы на вопрос 7
3
78

Вы можете попробовать использовать функцию 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() {
    ...вырезано...
    // Похоже, пришло время для 404.
    $wp_query->set_404();
    status_header( 404 );
    nocache_headers();
    ...вырезано...
}

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

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

24 мар. 2013 г. 20:17:28
Комментарии

Фрагмент кода Code 2, который вы опубликовали, работает идеально. set_header() — это как раз то, чего не хватало.

RRikesh RRikesh
25 мар. 2013 г. 07:11:42

@birgire вы упоминаете set_header() для добавления HTTP/1.1 404 Not Found, но в своём коде использовали status_header()?

henrywright henrywright
8 сент. 2014 г. 16:08:48

@henrywright похоже, здесь опечатка, я обновил ответ, спасибо ;-)

birgire birgire
8 сент. 2014 г. 16:45:24
2
23

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

add_action( 'wp', 'force_404' );
function force_404() {
    global $wp_query; //$posts (если требуется)
    if(is_page()){ // ваше условие
        status_header( 404 );
        nocache_headers();
        include( get_query_template( '404' ) );
        die();
    }
}
24 мар. 2013 г. 20:42:04
Комментарии

Удобно. Я проверяю пользовательские параметры запроса, поэтому не использую action, но это делает метод очень полезным в классе моего плагина.

John Reid John Reid
17 окт. 2014 г. 11:26:56

Добавьте следующее, чтобы исправить заголовок страницы: global $wp_query; $wp_query->is_404 = true;

brettwhiteman brettwhiteman
25 февр. 2016 г. 00:18:54
0

Наиболее надежный способ, который я нашел для достижения этого, — использовать фильтр template_include, как показано ниже:

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");
1 февр. 2022 г. 17:33:22
1

Я бы не рекомендовал принудительно вызывать 404 ошибку.

Если вы беспокоитесь о поисковых системах, почему бы просто не добавить метатег "no-index,no-follow" на эти страницы и заблокировать их через 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, но я считаю, что использование шаблона страницы может быть лучшим вариантом.

источник

22 мар. 2013 г. 10:47:21
Комментарии

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

RRikesh RRikesh
22 мар. 2013 г. 11:23:15
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.

Надеюсь, это решение поможет кому-то ещё.

4 окт. 2019 г. 21:20:53
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();
    }
}
21 июл. 2014 г. 15:24:48
Комментарии

Перенаправление при ошибках крайне негативно сказывается на ранжировании страницы. Вместо этого лучше отображать шаблон по тому же адресу, где был получен некорректный запрос. Если вы сделаете перенаправление, вот что произойдет: сначала будет установлен статус 404, затем перенаправление изменит его на 301 или 302, которое перенаправит на страницу с кодом 200. В результате поисковые системы проиндексируют эту страницу как валидную, хотя автор вопроса четко указал, что этого не хочет.

mopsyd mopsyd
15 мар. 2018 г. 03:43:12
3

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

Попробуйте подключить вашу функцию rr_404_my_event() к действию send_headers.

Я не уверен, возможно ли на этом этапе проверить ID записи, но попробуйте следующий вариант:

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 мар. 2013 г. 12:42:35
Комментарии

Я исправил некоторые синтаксические ошибки в вашем коде. У меня даже не загружается шаблон 404 с этим.

RRikesh RRikesh
22 мар. 2013 г. 12:48:41

Возможно, в вашем файле 404.php можно загрузить другой header.php, например <?php get_header('404'); ?>, чтобы загрузить header-404.php. В этом заголовке вы должны добавить header('HTTP/1.0 404 Not Found'); в разделе <head>.

Marc Dingena Marc Dingena
22 мар. 2013 г. 13:07:07

@MarcDingena Думаю, вам нужно разместить строку header() выше той, где вы выводите содержимое шаблона, иначе вы получите правильную страницу шаблона, но реальный HTTP-статус код всё равно будет 200.

David Wolf David Wolf
26 февр. 2022 г. 22:28:16