Как правильно организовать страницу ошибки 404 в своем плагине для WordPress?

Обращаюсь с просьбой о помощи, так как, возможно, я неправильно решил задачу и был бы признателен за корректный подход. 

Задача состоит в следующем: 
1) Имеется страница по адресу /aaa/, на которой размещен список элементов (элементы не являются постами);
2) У каждого элемента есть детальная страница по адресу /aaa/[a-z]+/. Глубже иерархия не предусмотрена;
3) Для несуществующих элементов необходимо отображать страницу с ошибкой 404 и статусом 404.

Что было сделано: 
1) В текущую тему добавлен шаблон template-aaa.php;
2) В данном шаблоне используется экземпляр класса из кастомного плагина: 
<pre><code class="php">&lt;?php
$publicArea = new MyPlugin\PublicArea();
$publicArea-&gt;show();</code></pre>
3) В административной панели создана страница с ярлыком "aaa", для которой назначен шаблон template-aaa.php. 

Теперь по поводу плагина: 
Плагин использует хуки: 
- init - для add_rewrite_tag() и add_rewrite_rule();
- query_vars - как партнер для add_rewrite_tag(); 
- get_header - здесь вызывается метод, который через get_query_var() определяет, что запрашивается детальная страница элемента, получает данные элемента. Если данные не были получены, выполняется следующий код: 
<pre><code class="php">&lt;?php
global $wp_query;
$wp_query-&gt;set_404();
status_header(404);</code></pre>

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

Итог: 
При HEAD-запросе для несуществующего элемента возвращается статус 200, в то время как при GET-запросе возвращается статус 404, что является верным поведением. 

Что необходимо изменить, чтобы для HEAD-запроса также возвращался статус 404?
  • 23 марта 2025 г. 21:24
Ответы на вопрос 2
Чтобы обеспечить корректное поведение вашего плагина для всех типов HTTP-запросов, включая HEAD, необходимо использовать правильные хуки и методы для обработки запросов в WordPress. Вам нужно убедиться, что ответ на HEAD-запрос также возвращает статус 404, если объект не найден.

Решение может заключаться в следующем:

### 1. Использование `template_redirect` или `template_include`

Вместо использования `get_header`, попробуйте использовать хук `template_redirect`. Он сработает перед тем, как WordPress начнет загружать шаблон, и позволяет установить статус ответа для всех типов запросов, включая HEAD.

### Пример кода

Замените ваш вызов, который пытается установить 404-статус, следующим образом:

```php
add_action('template_redirect', 'handle_404_for_nonexistent_items');

function handle_404_for_nonexistent_items() {
    global $wp_query;

    // Давайте убедимся, что у нас правильный контекст запроса
    if (is_page('aaa')) {
        // Получите переменную запроса, чтобы узнать, идёт ли речь о детальной странице элемента
        $item_slug = get_query_var('your_custom_query_var'); // замените 'your_custom_query_var' на свой ключ

        // Полезно может быть добавить условие для проверки сущности
        if ($item_slug && !is_item_exists($item_slug)) { // Напишите функцию is_item_exists($slug) для проверки существования элемента
            // Устанавливаем статус 404
            $wp_query->set_404();
            status_header(404);
            // Можно также вставить сюда редирект на страницу ошибки 404, если вы хотите:
            // include(404.php);
            exit; // Выход, чтобы предотвратить дальнейшую обработку
        }
    }
}
```

### 2. Убедитесь, что метод is_item_exists() правильно работает

Эта функция должна проверять, существует ли элемент по предоставленному слагу. Если элемента нет, функция должна вернуть `false`.

### Примечания

- Убедитесь, что у вас правильно настроены полученные значения переменных для `get_query_var()`, которые вы используете для извлечения слага элемента.
- Важно использовать `exit;` после установки статуса ответа 404, чтобы предотвратить дальнейшую обработку и вывести только заголовок.
- Если у вас есть конкретные условия, при которых вы хотите, чтобы страница 404 отображалась, убедитесь, что они корректно установлены.

При таком подходе вы сможете корректно обрабатывать HEAD-запросы так же, как и GET-запросы, возвращая статус 404 для несуществующих элементов.
Нужно вешать на правильный хук. Проверил на странице автора, отдает 404 

add_action('template_redirect', function (string $template): string {
    global $wp_query;
    if (!$wp_query->is_author()) {
        return $template;
    }
    $wp_query->set_404();
    status_header(404);
});


curl -I https://site.test/author/admin

HTTP/2 404
Похожие вопросы