多站点数据库升级声称成功,但db_version未更新

时间:2016-12-11 作者:sootsnoot

我已经运行WP core 4.4.2一段时间了,刚刚升级到4.6.1。我正在运行子目录多站点安装。

我无法使用自动更新。所以我停用所有插件,复制新的核心文件,以超级管理员身份登录,然后运行www.example.com/wp/wp-admin/network/upgrade.php . 当我单击链接Upgrade Network, 它循环浏览几个页面,列出所有站点(每页大约5个站点),然后说一切都完成了。

如果我使用phpMyAdmin并检查db_version 在各种wp_nnn_options 表中,该值不会因升级而更改。但它只会改变“根”站点的wp_options 桌子至少对于此更新。似乎对于以前的一些其他更新db_version 值在wp_nnn_options 表格。

对于此更新,如果我手动运行www.example.com/wp/wp-admin/sitename/upgrade.php 对于特定子站点,则db_version 是否在wp_nnn_options 该特定子站点的表。

这是正常/预期的行为吗?我应该避免手动运行吗upgrade.php 就个人子站点而言,只需信任网络升级就可以做正确的事情吗?

1 个回复
最合适的回答,由SO网友:sootsnoot 整理而成

感谢来自TheDeadMedic, 我知道我的问题是由我自己的应用程序环境引起的,我在问题中没有提供,因为我认为这与我的应用程序环境无关。Sorry about that! 我通常会在发帖时简要描述一下环境,但之前从未有过相关内容,所以这次我跳过了它:-(

我正在使用WordPress 作为Zend Framework MVC application 这需要登录。访问几乎所有WordPress 页面要求用户登录到ZF application; 如果没有登录ZF session 当发出请求时,请求被重定向到登录页面,并且登录页面显示一条消息,说明需要登录-但该页面显示的状态代码为200(奇怪的是,我最近考虑过在显示带有该消息的登录页面时提供401或403状态的更改,但我还没有这样做)。

网络升级。php脚本使用cURL 请求升级。网络中每个子站点的php脚本。这些cURL请求实际上得到了一个响应(重定向后),该响应只是ZF application; 但由于其状态代码为200,网络升级认为每个站点升级都成功了,每个人都很高兴,即使wp db中没有任何更改。

当我说根站点已升级时,我感到困惑/误解。我一定是手动更新了它,但忘记了在使用phpMyAdmin 查看数据库发生了什么。从备份开始,我可以看到,在运行网络升级时wp_*options 桌上有他们的db_version 更新(也没有wp_blog_versions 表得到更新)。

目前我可以手动更新每个子站点,因为只有10个,但这个数字应该会大幅增长。我想我会问一个新问题,看看有没有办法cURL 请求使用调用代码的PHP会话(ZF application 在会话中存储登录状态)。

The underlying problem and solution


如上所述cURL 请求(发生在WP_Http::request(), 呼叫人network/upgrade.php 要升级每个单独的子站点),请重定向到ZF application\'s 登录页面。这是因为他们没有访问与网络升级脚本相同的PHP会话,因为他们没有通过PHPSESSID 曲奇cURLWP_Http::request() 提供一种通过请求传递cookie的方法,并且有一个名为“http\\u request\\u args”的过滤器,可用于将cookie添加到请求中。我可以用它来通过PHPSESSID cookie改进了行为,但仍然不太正确。结果发现还有两个问题:

我要集成的代码WordPress 进入ZF application 阻止访问根站点,除非WordPress 用户是超级管理员。从那以后WordPress 使用cookie来维护登录状态,这些cookie还需要在运行升级脚本的请求中传递。显然,单个升级脚本本身没有检查WordPress 登录状态(!)。因此,我使用“http\\u request\\u args”过滤器在$_COOKIE 超全局。

当PHP会话处于活动状态时,保存会话数据的文件将被锁定。因此,为了让运行升级脚本的请求使用调用脚本的会话,调用脚本需要调用session_write_close() 解锁会话文件。WordPress本身没有问题,因为它不使用会话,但对于我与ZF application. 我无法轻松找到添加该调用的挂钩,因此我将其编辑到核心class-http.php 调用之前的文件Requests::request, 受我的ZF application 集成处于活动状态,PHP会话处于活动状态,并且正在向当前请求中指定的同一服务器发出请求:

if (ZF_PLUGGABLE_RUN && session_status() == PHP_SESSION_ACTIVE && $defaults[\'cookies\'] == $_COOKIE) {
    // PHP keeps session file locked, need to close it to allow the request to use it
    session_write_close();
}
我确实尽量避免编辑核心文件,但在很多地方,我都找不到合适的钩子。我将核心文件保存在git 并分别跟踪我在每个版本中更改的每个文件,以便获取一个新版本需要一个非常小的定义良好的合并过程。

Final solution without editing core file


尽管在调用之前没有钩子Requests::request(), 事实证明,“http\\u request\\u args”过滤器足够接近。因此,现在我已经删除了核心文件编辑,只需定义“http\\u request\\u args”过滤器,如下所示(在定义其他集成过滤器的类中WordPress 与我的ZF application). 我只在需要ZF application 集成是主动的,所以我不需要测试ZF_PLUGGABLE_RUN 常数:

public function http_request_args($args, $url) {
    $retval = $args;
    if (@parse_url($url, PHP_URL_HOST) == $_SERVER[\'SERVER_NAME\']) {
        // The request is going to our own server, so we need to provide it our current cookies,
        // including both PHPSESSID for the session holding the ZF user, and the WordPress cookies
        // holding the WordPress user.
        if (! array_key_exists(\'cookies\', $args)) {
            // The default array settings in WP_Http::request() include a \'cookies\' element,
            // so that element should always be present in $args.
            throw new Exception("Unexpected: \\$args does not contain an element name \'cookies\'");
        }
        if (! is_array($args[\'cookies\'])) {
            // The default value of $args[\'cookies\'] is an empty array, not null
            throw new Exception("Unexpected: \\$args[\'cookies\'] is not an array");
        }

        // In known example of self-directed requests for database update, $args[\'cookies\']
        // will be empty. But for generality, instead of assigning it a value, just merge in
        // the $_COOKIE superglobal, letting any user-specified cookies in $args[\'cookies\'] override.
        $retval[\'cookies\'] = array_merge($_COOKIE, $args[\'cookies\']);

        // PHP keeps the session file locked, so we need to close it to allow the request to use it
        if (session_status() == PHP_SESSION_ACTIVE) {
            session_write_close();
        }
    }
    return $retval;
 }

相关推荐

Multisite domain naming

我是wordpress多站点的新手。我们计划使用PaaS。我知道的内部子域可以映射。但是,我可以通过DNA使用外部子域(cname)来映射吗?例如我知道那个子域。mydomain。com是可能的,但子域是可能的。notmydomain。com是否可能?在托管方面,这种设置的要求/建议是什么。非常感谢。