Где, когда и как правильно очищать правила перезаписи в пределах плагина?

10

У меня немного странная проблема с правилами перезаписи, которые не обновляются должным образом.

Я пытался использовать flush_rewrite_rules();и flush_rewrite_rules(true);.

Я также пытался глобализировать, $wp_rewriteиспользуя $wp_rewrite->flush_rules();и$wp_rewrite->flush_rules(true);

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

В настоящее время я переписал правила, сбрасываемые при активации и деактивации плагина. Там нет проблем.

У меня есть страница настроек администрирования плагина для пользователей, чтобы настроить плагин. Некоторые параметры настраивают структуру постоянных ссылок, поэтому правила перезаписи необходимо сбросить на странице настроек администрирования плагина «Сохранить настройки». (Использует стандарт update_option();) для сохранения настроек.

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

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

Пользовательский тип записи зарегистрирован правильно и соответствующим образом. Я точно знаю, что это не проблема.

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

Пользовательские типы сообщений затем загружаются всегда и загружаются initкак обычно.

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

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

Что делает эта страница с настройками администрации, что я не делаю, что позволяет правилам перезаписи корректно сбрасываться, а мои нет?

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

Есть ли в WordPress определенный момент, когда сброс правил перезаписи просто не сбрасывает ВСЕ правила больше?

admin_menu - Добавлена ​​страница настроек плагина для администрирования WordPress.

add_options_page() - Страница настроек плагина добавлена ​​в меню настроек.

Страница настроек отображается в обратном вызове для add_options_page(). Это также где $_POSTобрабатывается для обновления настроек плагина и очистки правил перезаписи.

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

Майкл Эклунд
источник
1
Похоже, у вас неправильный порядок вещей, трудно сказать, не увидев какой-то код. Страница администратора постоянных ссылок просто вызывает flush_rewrite_rules, которая просто удаляет rewrite_rulesопцию и восстанавливает ее, вы можете открыть файл wp-admin/options-permalinks.phpи посмотреть, где это происходит. так как эта операция просто удаляет весь параметр, невозможно частично очистить правила.
Майло
@ Мило, я думаю, ты прав. У меня есть класс, который загружается на initкоторый регистрирует типы сообщений. Я подумал, что настройки страницы сохраняются, и страница перезагружается ... затем initснова запускается, чтобы зарегистрировать необходимые типы записей. Поэтому я решил, что типы сообщений уже будут загружены, и все, что мне нужно было сделать, это обновить опцию, а затем сбросить правила перезаписи со страницы настроек моего плагина. Я выложу ответ, как я нашел решение.
Майкл Эклунд
Просто предупреждение flush_rewrite_rules () в моем плагине оказалось для меня частью проблемы. Я удалил php hook и в итоге просто обновил постоянные ссылки вручную, и мои ошибки CPT 404 исчезли.
Myol

Ответы:

4

Лучшее место для сброса правил переписывания - активация / деактивация плагина.

function myplugin_activate() {
    // register taxonomies/post types here
    flush_rewrite_rules();
}

register_activation_hook( __FILE__, 'myplugin_activate' );

function myplugin_deactivate() {
    flush_rewrite_rules();
}
register_deactivation_hook( __FILE__, 'myplugin_deactivate' );

Смотрите статью кодекса

Заранее извиняюсь, я не прошел весь ваш вопрос, так что это немного ответ печенья.

helgatheviking
источник
1
Спасибо за ваше предложение, но я знаю об этом. Проблема не в активации плагинов / деактивации плагинов. Это связано с тем, что пользователи меняют настройки на уже активный плагин, который регулирует правила перезаписи, что требует сброса.
Майкл Эклунд
1
Я думал, что это может быть так, но я очень устал, когда читал твой вопрос. Решение Ялоцина выглядит многообещающе, надеюсь, вы с ним справились.
Helgatheviking
4

Трудно сказать, что не так, не видя ваш код. Но после сохранения некоторых настроек удобно подключиться, admin_initкак показано ниже, чтобы сбросить правила перезаписи.

Код:

add_action('admin_init', 'wpse_123401_plugin_settings_flush_rewrite');
function wpse_123401_plugin_settings_flush_rewrite() {
    if ( get_option('plugin_settings_have_changed') == true ) {
        flush_rewrite_rules();
        update_option('plugin_settings_have_changed', false);
    }
}


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


Примечание: не проверено

Nicolai
источник
2
Или вы могли бы использовать переходный процесс, может быть? Но определенно +1 за то, что не сбрасывает правила на каждый admin_init.
Helgatheviking
Вы, конечно, правы в отношении переходного процесса, я думаю, что я выбрал *_option()из-за страницы настроек. @helgatheviking
Николай
Это было очень полезно. У меня была похожая ситуация с Майклом. В итоге я включил предложение Хельги об использовании переходного процесса и установил его в функции проверки настроек. Мне пришлось установить переходный режим на false после сброса, иначе он просто продолжал сбрасываться при каждой загрузке страницы администратора, пока не закончился переходный процесс. Так что функционально с использованием опции или переходного процесса было то же самое. Я полагаю, что переходный процесс может быть хорошим, просто чтобы таблица параметров была немного чище. Но незначительный момент.
MatthewLee
Разница на самом деле незначительна, особенно если переходные процессы постоянны, не имеют срока действия, но, конечно, переходные процессы имеют и другие возможности, преимущества, которые приятно иметь. @MatthewLee
Николай
3

У меня был файл класса типов постов, который отвечал за чтение настроек опций плагина и создание необходимых пользовательских типов постов на основе заданных пользователем настроек.

Этот файл классов типов сообщений был загружен на крючок init.

Я решил, что все, что мне нужно будет сделать, это обновить настройки плагина, а затем сбросить правила перезаписи. Так как класс типов сообщений уже был загружен на основе настроек плагина. Но со страницами администрирования они загружаются ПОСЛЕ initкрючка.

Типы записей никогда не были зарегистрированы, потому что настройки еще не были установлены. Класс регистрации типов записей закончился преждевременно, и типы записей не были зарегистрированы.

Решение было:

  1. Обновите настройки плагина.
  2. Загрузите файл класса типов сообщений ТОЛЬКО один раз, чтобы были созданы новые правила перезаписи.
  3. Сбросьте правила перезаписи.

(Ранее ... step2 отсутствовал - как упомянуто выше ...)

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

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

Мне также пришлось добавить вызов flush_rewrite_rules();на странице настроек администрирования плагина.

Так что ради обеспечения того, чтобы все сбрасывалось ...

Шаг 1) Перейдите на страницу настроек администрирования плагина. - Первоначальная промывка.

Шаг 2) Обновите настройки плагина. - Второй поток.

Шаг 3) Страница перенаправляет на страницу настроек плагина. Вызывает ... Третий и последний сброс (аналогично первоначальному сбросу - выполняется автоматически при посещении страницы настроек плагина)

Я не говорю, что это практическое решение, но оно сработало для меня. Очень странная проблема и, скорее всего, связана с моей инфраструктурой кодирования.

Майкл Эклунд
источник
1

@ tazo-todua это сработало и у меня при использовании мультисайта.

add_action( 'wpmu_new_blog', 'set_my_permalink_structure', 11, 2 );

function set_my_permalink_structure( $blog_id ) {

    switch_to_blog( $blog_id );

    global $wp_rewrite;
    $wp_rewrite->set_permalink_structure( '/%postname%/' );
    $wp_rewrite->flush_rules();
    $wp_rewrite->init();

    restore_current_blog();
}
stillatmylinux
источник
0

МОЕ найденное решение было:

global $wp_rewrite; $wp_rewrite->flush_rules(); $wp_rewrite->init();
T.Todua
источник
0

У меня была точно такая же проблема. В моем плагине у меня есть типы записей, которые создаются динамически. Поэтому они не могут быть зарегистрированы с помощью register_post_type()статического метода во время activation_hookи, следовательно, еще не активны, когда flush_rewrite_rules()запускаются во время этого перехвата (что обычно является рекомендуемым способом сброса правил перезаписи).

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

Необходимость промывки можно определить, посмотрев на результат get_option( 'rewrite_rules' ):

class MyPostTypeClass {

public final function register_as_custom_post_type() {
    ...   //do all the setup of your post type here     
    $args = array(
                  ... //populate the other arguments as you see fit
                  'rewrite' => array('slug' => 'slug-of-your-post-type')
                 );
    register_post_type('post-type-name-of-your-post-type', $args );

    $rewrite_rules_must_be_fluhed = true;
    foreach( get_option( 'rewrite_rules' ) as $key => $rule)
        if(strpos($key, $args['rewrite']['slug'] ) === 0)
        {
            $rewrite_rules_must_be_fluhed = false;
            break;
        }
    if($rewrite_rules_must_be_fluhed)
        flush_rewrite_rules(true);
}
}

Недостатки:

  • В какой-то степени зависит от того, какие именно правила перезаписи WP генерирует во время register_post_type().
  • Проверка необходимости очистки во время каждой загрузки страницы также создает некоторые накладные расходы.

Преимущества:

  • Полностью инкапсулирован в классе, представляющем тип записи.
  • Сбрасывает правила перезаписи, только если это действительно необходимо.

Используйте это только в том случае, если вы не можете зарегистрировать свой тип записи в статической функции, которая может вызываться как во время, так initи в activation_hook!

Зависимость от того, как register_post_type()выглядят правила перезаписи, сгенерированные во время, можно уменьшить, заменив тест if(strpos($key, $args['rewrite']['slug'] ) === 0)более сложным, то есть регулярным выражением.

cgogolin
источник