更新帖子超过最大执行时间

时间:2016-02-21 作者:Giorgi Nakeuri

史前时期How to generate slugs?:

我有以下情况。我不小心更新了post_name 中的列wp_posts 所有行的表。现在我需要以某种方式更新这些内容。

我已实施以下解决方案:

<?php
    /*
    Plugin Name: Your Plugin
    Plugin URI: http://www.example.com
    Description: description
    Version: 0.1
    Author: thatsyou
    Author URI: http://www.yourdomain.com
    License: MIT
    */

$update_count = 0;

for ($x = 0; $x <= 7823; $x++)
{
    $post = get_post($x);

    if (!empty($post))
    {
        // check the slug and run an update if necessary 
        $new_slug = sanitize_title( $post->post_title );

        // use this line if you have multiple posts with the same title
        $new_slug = wp_unique_post_slug( $new_slug, $post->ID, $post->post_status, $post->post_type, $post->post_parent );

        if ( $post->post_name != $new_slug )
        {
            wp_update_post(
                array (
                    \'ID\'        => $post->ID,
                    \'post_name\' => $new_slug
                )
            );

            $update_count+=1;
        }
    }
}

echo $update_count;
?>
我正在迭代所有需要的IDs、 选择post并更新其slug。当我激活插件时,它似乎起作用了,我想它然后卡在了在中间的某个地方。这是什么原因?

我还注意到,它不会为以下修订生成slug9-revision-v1. 确实如此title 修订消毒。我不知道,其他类型的帖子可能会有更多的不一致之处。我只是不擅长这个领域。

我还看到了用插件更新的3行(post_modified 与我激活插件时相同),但是post_names对于那些是一样的。我在期待wp_unique_post_slug 将生成不同的帖子名称。

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

你确实有大量的帖子will 使用如此昂贵的操作使服务器崩溃(由于超过了最长执行时间)。我们需要以一种更聪明的方式来运行它。

首先,我们想得到所有的帖子,除了revisionnav_menu_item. 修订post_names是以不同的方式构建的,尝试用其他post类型处理它们也会使服务器崩溃

其次,我们需要在WP_Query 为了只获取帖子的ID、post\\u name、post\\u title、post\\u status、post\\u type和post\\u parent字段。这将大大减轻服务器的压力

第三,我们需要忽略更新所有术语和后期元缓存。这也给您的资源增加了额外的不必要的压力,所以我们需要排除更新它们,因为坦率地说,我们不需要post terms和meta

除了修订版以外的所有帖子类型,如果有这么多的帖子,您可能需要运行几次,但是如果您使用的代码有了巨大的改进,您可能只需要运行一次就可以了

您可以尝试以下操作:(您可以将其放入functions.php 或者用我的代码替换插件中的现有代码

add_action( \'wp\', function ()
{
    global $wpdb;

    add_filter( \'posts_fields\', function ( $fields, \\WP_Query $q ) use ( $wpdb )
    {
        remove_filter( current_filter(), __FUNCTION__ );

        // Only target a query where the new custom_query parameter is set with a value of custom_meta_1
        if ( \'custom_meta_1\' === $q->get( \'custom_query\' ) ) {
            // Only get the ID, post_name, post_title, post_status, post_type and post_parent fields to reduce server load
            $fields = "
                $wpdb->posts.ID,
                $wpdb->posts.post_title,
                $wpdb->posts.post_name,
                $wpdb->posts.post_type,
                $wpdb->posts.post_status,
                $wpdb->posts.post_parent
            ";
        }

        return $fields;
    }, 10, 2);

    // Get all public post types
    $post_types = get_post_types( [\'public\' => true] );

    $args = [
        \'post_type\'              => $post_types,
        \'posts_per_page\'         => -1,              
        \'suppress_filters\'       => false,           // Allow the posts_fields filter
        \'custom_query\'           => \'custom_meta_1\', // New parameter to allow that our filter only target this query
        \'update_post_term_cache\' => false,
        \'update_post_meta_cache\' => false
    ];
    $q = get_posts( $args );

    // Make sure we have posts before we continue, if not, bail
    if ( $q ) {

        // Loop through the posts
        foreach ( $q as $single_post ) {
            // Sanitize our post title
            $new_slug = sanitize_title( $single_post->post_title );

            // Check if our $new_slug is not equal to our post_name
            if ( $single_post->post_name === $new_slug )
                continue; // Do nothing further

            // Our new slug and post name does not match, lets save a unique post_name
            $post_name = wp_unique_post_slug( 
                $new_slug, 
                $single_post->ID,
                $single_post->post_status, 
                $single_post->post_type, 
                $single_post->post_parent       
            );

            // Last change to bail before we update the post_name field
            if ( false !== stripos( $single_post->post_name, $post_name ) )
                continue;

            //Update the post_name field, wpdb::update is the quickest
            $wpdb->update(   
                \'wp_posts\', 
                [\'post_name\' => $post_name],    // string
                [\'ID\'        => $single_post->ID], 
                \'%s\',
                \'%s\' 
            );  
        } // endforeach $q
    }
}, PHP_INT_MAX );
编辑-修订如上所述,上述代码应用于所有职位,但作为修订的修订除外post_name 是以不同的方式构建的。

以下代码将更新post_name 修订字段。你不应该把这段代码和上面的代码一起运行,它肯定会让你的服务器因为你的帖子数量而崩溃。您应该运行代码块1,删除它,然后运行代码块2,一旦完成就删除它,特别是代码块2,因为它非常昂贵。

代码如下:

add_action( \'wp\', function ()
{
    global $wpdb;

    add_filter( \'posts_fields\', function ( $fields, \\WP_Query $q ) use ( $wpdb )
    {
        remove_filter( current_filter(), __FUNCTION__ );

        // Only target a query where the new custom_query parameter is set with a value of custom_meta_1
        if ( \'custom_meta_1\' === $q->get( \'custom_query\' ) ) {
            // Only get the ID, post_name, post_title, post_status, post_type and post_parent fields to reduce server load
            $fields = "
                $wpdb->posts.ID,
                $wpdb->posts.post_title,
                $wpdb->posts.post_name,
                $wpdb->posts.post_type,
                $wpdb->posts.post_status,
                $wpdb->posts.post_parent
            ";
        }

        return $fields;
    }, 10, 2);

    $args = [
        \'post_type\'              => \'any\',
        \'post_status\'            => \'any\',
        \'posts_per_page\'         => -1,
        \'custom_query\'           => \'custom_meta_1\', // New parameter to allow that our filter only target this query
        \'update_post_term_cache\' => false,
        \'update_post_meta_cache\' => false
    ];
    $q = get_posts( $args );

    // Make sure we have posts before we continue, if not, bail
    if ( $q ) {
        // Now we can get the post revions and loop throught them
        foreach ( $q as $single_post ) {
            $rev_args = [
                \'post_type\'              => \'revision\',
                \'post_status\'            => \'inherit\',
                \'post_parent\'            => $single_post->ID,
                \'posts_per_page\'         => -1,
                \'order\'                  => \'ASC\',
                \'custom_query\'           => \'custom_meta_1\', // New parameter to allow that our filter only target this query
                \'update_post_term_cache\' => false,
                \'update_post_meta_cache\' => false
            ];
            $revisions = get_posts( $rev_args );

            // Make sure we have revions before we continue
            if ( $revisions ) {
                // Loop through the revisions and set post_name
                foreach ( $revisions as $key=>$revisions ) {
                    // Build a revision post slug in the format {$post->post_parent}-revision-v{$key + 1}
                    $post_name = $single_post->ID . \'-revision-v\' . ( $key + 1 );

                    // Make sure that we don\'t have a post_name yet with the name $post_name
                    if ( $revisions->post_name === $post_name )
                        continue; // Do nothing

                    //Update the post_name field, wpdb::update is the quickest
                    $wpdb->update(   
                        \'wp_posts\', 
                        [\'post_name\' => $post_name],    // string
                        [\'ID\'        => $revisions->ID], 
                        \'%s\',
                        \'%s\' 
                    );  
                }
            }
        }
    }
}, PHP_INT_MAX );
编辑-在2015-07-08 23:23:45和2016-02-21 09:42:31之间

如果您只需要针对两个特定日期之间的帖子和修订,您可以在查询参数中添加以下内容$args 在两个代码块中date_query

\'date_query\' => [
    [
        \'after\'     => \'2015-07-08 23:23:45\',
        \'before\'    => \'2016-02-21 09:42:31\',
    ],
],
所以

$args = [
    \'post_type\'              => $post_types,
    \'posts_per_page\'         => -1,              
    \'suppress_filters\'       => false,           // Allow the posts_fields filter
    \'custom_query\'           => \'custom_meta_1\', // New parameter to allow that our filter only target this query
    \'update_post_term_cache\' => false,
    \'update_post_meta_cache\' => false
];
在块中,一变成

$args = [
    \'post_type\'              => $post_types,
    \'posts_per_page\'         => -1,              
    \'suppress_filters\'       => false,           // Allow the posts_fields filter
    \'custom_query\'           => \'custom_meta_1\', // New parameter to allow that our filter only target this query
    \'update_post_term_cache\' => false,
    \'update_post_meta_cache\' => false,
    \'date_query\'             => [
        [
            \'after\'          => \'2015-07-08 23:23:45\',
            \'before\'         => \'2016-02-21 09:42:31\',
        ],
    ],
];

相关推荐

500 Internal Errors

我正在将当前的Eduma主题更新为最新版本(3.0.9.1),目前的版本是3.0.7。我正在运行WordPress 4.7.5。但是,在运行更新时,我得到Update Failed: Internal Server Error 安装过程中的消息。所以我启动了这个过程,它运行了一分钟,然后它就停止了工作,我陷入了维护模式。所以我必须手动删除.maintenance 来自我的服务器的文件。我截图了我在错误中看到的内容。我在WordPress网站上运行了调试模式,这就是我所拥有的[31-May-2017 15: