在插件的作用域中,何时何地以及如何正确地刷新重写规则?

时间:2013-11-15 作者:Michael Ecklund

我遇到了一个有点奇怪的问题,重写规则没有正确刷新。

我试过使用flush_rewrite_rules();flush_rewrite_rules(true);.

我也尝试过全球化$wp_rewrite 使用$wp_rewrite->flush_rules();$wp_rewrite->flush_rules(true);

这两种方法似乎都没有正确刷新重写规则。这些调用在调用时确实刷新了重写规则。我怎么知道的?将解决方案用于debugging rewrite rule flushing.

目前,我已经重写了插件激活和停用的规则。没有问题。

我有一个插件管理设置页面,供用户配置插件。一些设置会调整永久链接结构,因此需要在插件管理设置页面“保存设置”上刷新重写规则。(使用标准update_option();) 用于保存设置。

我想指出的是,根据指定的设置,将创建自定义帖子类型以匹配用户指定的设置。因此,必须在保存设置后立即刷新重写规则。这就是事情不能正常运作的地方。

上述用于调试重写规则的链接解决方案由提供@toscho 显示它正在刷新大量重写规则。然而,当访问自定义帖子类型的单一项,甚至是自定义帖子类型的存档时,每个都会返回404个错误。

已正确且适当地注册自定义帖子类型。我肯定这不是问题所在。

紧接着插件管理页面设置保存。创建自定义帖子类型,调整permalink结构,并尝试刷新所有重写规则。

然后始终加载自定义帖子类型,并加载到init 就像平常一样。

出于某种原因,重写规则没有正确刷新,因为正如我之前所说的,访问自定义post类型的singular或archive部分会返回404错误。

奇怪的是,如果我只需访问administration permalinks设置页面,然后返回前端查看自定义帖子类型的单数部分或归档部分,它们就会像预期的那样神奇地工作。

What does that administration permalinks settings page do that I\'m not doing that allows the rewrite rules to flush appropriately and mine do not?

我的意思是,作为一个临时解决方案,在保存插件管理设置页面后,我会将用户重定向到管理permalinks设置页面,但这不是一个理想的解决方案。我更喜欢重写规则在插件代码中正确刷新。

WordPress中是否存在这样一种情况:刷新重写规则不再刷新所有规则?

admin_menu - 插件设置页面已添加到WordPress管理中。

add_options_page() - 插件设置页面添加在设置菜单下。

设置页面在回调中呈现add_options_page(). 这也是$_POST 用于更新插件设置和刷新重写规则。

由于这已经是一个很长的问题,我愿意在场外链接中提供代码块(如果有帮助的话),以帮助生成有效的答案。

7 个回复
SO网友:helgatheviking

刷新重写规则的最佳位置是插件激活/停用。

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

See the codex article

提前道歉,我没有完全回答你的问题,所以这是一个千篇一律的回答。

SO网友:Nicolai Grossherr

如果看不到您的代码,就很难判断出问题所在。但在保存一些设置后,连接到admin_init 如下图所示刷新重写规则。

Code:

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

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


注:未测试

SO网友:Michael Ecklund

我有一个帖子类型类文件,负责读取插件的选项设置,并根据用户指定的设置创建必要的自定义帖子类型。

此post types类文件已加载到挂钩上init.

我想接下来我需要做的就是更新插件设置,然后刷新重写规则。因为post types类已经根据插件设置加载。但对于管理页面,它们是在init

帖子类型从未实际注册过,因为设置尚未实际设置。post types注册类最终提前终止,没有注册任何post类型。

The solution was:

<更新插件设置(之前……缺少步骤2——如上所述……)

从现在起,帖子类型将加载到init 钩子,并且已经指定了设置,允许创建帖子类型并与适当的重写规则配对。

出于任何原因,在执行了上述三个步骤之后,我不得不添加一个JavaScript调用以重定向到当前页面。

我还必须给flush_rewrite_rules(); 在插件的管理设置页面上。

所以为了确保所有东西都冲洗干净。。。

步骤1)导航到插件的管理设置页面。-初始冲洗。

步骤2)更新插件设置。-第二次冲洗。

步骤3)页面重定向到插件的设置页面。导致。。。第三次和最后一次刷新(与初始刷新相同--在访问插件的设置页面时自动完成)

我并不是说这是一个切实可行的解决方案,但它对我有效。非常奇怪的问题,很可能与我的编码基础设施有关。

SO网友:cgogolin

我也有同样的问题。在我的插件中,我有动态创建的帖子类型。因此,他们不能通过register_post_type()activation_hook 因此,当flush_rewrite_rules() 在此挂钩期间运行(通常是recommended way 刷新重写规则)。

最后,我能想到的最干净的解决方案是在注册post类型后刷新重写规则,但当然只有在确实需要这样刷新的情况下(因为操作很慢)。在我的例子中,实际上我有几个自定义的post类型,它们继承自一个基类,因此需要实现在那里进行刷新的代码。

是否需要冲洗可以通过查看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().

完全封装在表示post类型的类中只有在无法在静态函数中注册帖子类型时,才可以使用此选项,该函数可以在init 以及activation_hook!

对重写规则生成方式的依赖性register_post_type() 看起来可以通过更换测试来缓解if(strpos($key, $args[\'rewrite\'][\'slug\'] ) === 0) 使用更复杂的东西,即正则表达式。

SO网友:stillatmylinux

@tazo todua使用multisite时,这对我也很有用。

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

SO网友:JesusIniesta

如果要在激活或停用任何插件时刷新\\u rewrite\\u规则

add_action(\'init\', function(){

    // Get the path of every plugin installed
    $pluginsInstalledPaths = glob(WP_PLUGIN_DIR . \'/*\', GLOB_ONLYDIR);

    foreach ($pluginsInstalledPaths as $pluginPath) {
        // Get all PHP files available in the plugin root directory
        $files = glob($pluginPath . \'/*.php\');
        foreach ($files as $file) {
            $contents = file_get_contents($file);
            // If the file contains "Plugin Name" it is the main plugin file
            if (preg_match(\'/\\/\\*\\*[^\\/]*?Plugin Name:/\', $contents)) {
                add_action(\'activate_\' . plugin_basename($file), function(){
                    flush_rewrite_rules();
                });
                add_action(\'deactivate_\' . plugin_basename($file), function(){
                    flush_rewrite_rules();
                });
            }
        }
    }
});

SO网友:T.Todua

我找到的解决方案是:

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

结束

相关推荐

change backend header options

Wordpress在“设计”选项卡下提供了标题和背景的后端页面,可以在函数内部激活。php。是否可以自定义该选项?例如,我想有可能选择一个标志。或者,最好不要更改这些页面,而是将自定义标题/背景选项集成到我的主题的选项选项卡中?