Исключение пути в WordPress с помощью перенаправлений в .htaccess (Apache)
Я хочу исключить путь, соответствующий правилу, из загрузки WordPress. Обычно я решаю это с помощью флага [L]
в правиле перед всеми остальными.
Для упрощения примера, предположим, что я хочу сопоставить простой путь /foo/
.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^foo/?$ - [L]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
Однако это не работает. Несколько других вариантов предложены в этом старом посте на Stack Overflow, но ни один из них не работает (ни у меня, ни у кого-либо в комментариях к тому посту).
Я также пробовал это условие перезаписи вместо правила:
RewriteCond %{REQUEST_URI} ^/?(foo/.*)$
А также добавление ErrorDocument 401 default
в конец файла .htaccess
.
Вам следует использовать RewriteCond
вместо RewriteRule
. Используйте это:
RewriteCond %{REQUEST_URI} !/foo/
Таким образом, полный код может выглядеть так:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_URI} !/foo/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

Одна небольшая загвоздка заключается в том, что вам нужно обновить RewriteRule ./
в предпоследней строке. Вот обновлённый (и протестированный) фрагмент для вас:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_URI} !^/foo/.*$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ./ /index.php [L]
</IfModule>
# END WordPress
Я протестировал оба варианта:
Надеюсь, это поможет!!

Вот и всё, спасибо. Хотя я не уверен, почему .
не соответствует ./
, должно было соответствовать обоим. Для тех, у кого возникнет эта проблема в будущем: я немного оптимизировал, изменив на ./?
и написал небольшой сервис для проверки файла .htaccess
, чтобы убедиться, что некоторые плагины или обновления не перезаписали/сбросили его.

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

Да, согласен. Файл по-прежнему полностью доступен для записи. На самом деле у меня уже был сервис, который записывает мой собственный блок в .htaccess
внутри моей темы, так что я просто расширил его. Он ищет определённую строку, изменяет её при выполнении условия и затем записывает изменение в специальный лог.

Следующее правило работает для меня:
RewriteRule ^(foo)($|/) - [L]
Это означает, что любой путь, начинающийся с foo, например /foo/, /foo/bar/ или что-то подобное, приводит к Apache 404 вместо темы 404; при условии, что фактического каталога с таким путем не существует.
Правило должно быть перед последней стандартной строкой блока WordPress:
RewriteRule . /index.php [L]
И не имеет значения, если оно находится после RewriteBase /
, оно может быть и до него; ранее это было просто поспешно и небрежно сформулировано с моей стороны.
Это даст вам возможность оставить блок между # BEGIN WordPress
и # END WordPress
нетронутым, если вы хотите. Поместив
<IfModule mod_rewrite.c>
RewriteRule ^(foo)($|/) - [L]
</IfModule>
перед # BEGIN WordPress
.
Возможно, вы захотите предотвратить создание пути /foo/ в WordPress, вот что пришло на ум:
add_filter( 'wp_unique_post_slug', 'no_more_foo_wp_unique_post_slug', 2, 6 );
function no_more_foo_wp_unique_post_slug(
$slug, $post_ID, $post_status, $post_type, $post_parent, $original_slug
) {
if ( $post_parent === 0 ) {
$pattern = '/^foo$/';
$replace = 'bar';
$slug = preg_replace( $pattern, $replace, $slug );
}
return $slug;
}

Вы правы, что я должен был установить своё правило после базового, не уверен, почему я сделал это до в этом посте! На самом деле в рабочем .htaccess
оно было установлено после. Спасибо, что обратили внимание. Это была моя ошибка при редактировании markdown здесь.
