在何处,何时何地以及如何在插件范围内正确刷新重写规则?


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并查看发生的位置。由于此操作只会删除整个选项,因此无法部分刷新规则。
米洛

@Milo我认为你是对的。我有一个加载init该职位类型的类。我认为,页面设置已保存,页面将重新加载...然后init再次触发该钩子以注册必要的帖子类型。因此,我认为帖子类型已经加载,我需要做的就是更新该选项,然后从插件设置页面中刷新重写规则。我将发布一个解决方案的答案。
Michael Ecklund

在我的插件中仅出现警告flush_rewrite_rules()最终对我来说是问题的一部分。我删除了php hook,最终只是手动更新了永久链接,我的CPT 404错误消失了。
myol 2014年

Answers:


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

参见法典文章

事先表示歉意,我并没有完全解决您的问题,因此这有点千篇一律。


1
感谢您的建议,但我知道这一点。问题不在于插件激活/插件停用。它与用户将设置更改为已经处于活动状态的插件有关,后者会调整重写规则,因此需要刷新。
Michael Ecklund

1
我以为可能是这样,但是在阅读您的问题时我感到非常疲倦。ialocin的解决方案看起来很有希望,希望您能解决。
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);
    }
}


您必须在设置页面的某个位置设置该选项,或者确切地说是在保存设置的过程中的某个位置。没有选项的情况下这样做很不好,因为您不想每次都刷新规则。


注意:未经测试


2
还是可以使用瞬变?但肯定是+1,因为它不刷新每个admin_init上的规则。
helgatheviking

您当然对瞬态是正确的,我猜是*_option()因为设置页面,所以我选择了瞬态。@helgatheviking
Nicolai

这非常有帮助。我和迈克尔有类似的情况。我最终结合了Helga关于使用瞬态的建议,并在设置的验证功能中进行了设置。我最终需要在刷新后将瞬态设置为false,否则它只会在每次管理页面加载时保持刷新状态,直到瞬态过期为止。因此,在功能上使用期权或暂时期权是相同的。我猜想瞬态可能只是保持选项表更整洁的一种方式。但这是一个小问题。
MatthewLee 2014年

差异确实很小,尤其是在瞬变是永久性的,未过期的情况下,但是瞬态当然具有其他功能,这是很好的好处。@MatthewLee
Nicolai

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

0

我找到的解决方案是:

global $wp_rewrite; $wp_rewrite->flush_rules(); $wp_rewrite->init();

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在WP期间生成的确切重写规则register_post_type()
  • 在每次页面加载期间检查是否有必要进行刷新也会产生一些开销。

好处:

  • 完全封装在表示帖子类型的类中。
  • 仅在确实必要时刷新重写规则。

仅当无法在静态函数中注册帖子类型时才使用此功能,该静态函数可以在initactivation_hook!期间调用!

register_post_type()通过用if(strpos($key, $args['rewrite']['slug'] ) === 0)更精细的内容(即正则表达式)替换测试,可以减轻对外观期间生成的重写规则的依赖性。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.