【问题标题】:Why does this `while` loop not process all records when it changes the data?为什么这个`while`循环在更改数据时不处理所有记录?
【发布时间】:2020-08-18 16:21:21
【问题描述】:

我在 WordPress 脚本中有一个 PHP while 循环,当它修改数据时,它似乎只处理了它应该处理的一半记录,我很难理解为什么会发生这种情况。

我正在编写一个 WP-CLI 脚本,它将在所有尚未拥有它的 cmets 上设置一个带有键 reviewed 和值 1 的元数据。我的脚本如下所示:

class Mark_Comments_Reviewed {

    public function __invoke() {

        $limit  = 100;
        $offset = 0;

        while ( $comment_ids = $this->get_unreviewed_comments( $limit, $offset ) ) {

            array_walk(
                $comment_ids,
                function ( $comment_id ) {
                    $comment_id = (int) $comment_id;
                    $this->process_comment( $comment_id );
                }
            );

            $offset += $limit;
        }
    }

    protected function get_unreviewed_comments( int $limit, int $offset ): array {

        global $wpdb;

        return $wpdb->get_col(
            $wpdb->prepare(
                "SELECT DISTINCT comments.comment_ID
                        FROM wp_comments AS comments
                        AND comments.comment_ID NOT IN (
                            SELECT meta.comment_id
                            FROM wp_commentmeta AS meta
                            WHERE meta.meta_key = 'reviewed'
                        )
                        LIMIT %d
                        OFFSET %d",
                $limit,
                $offset
            )
        );
    }

    protected function process_comment( int $comment_id ): bool {
        return ! ! update_comment_meta( $comment_id, 'reviewed', (int) true );
    }

}

wp_commentmeta 表有字段meta_idmeta_key,meta_valueandcomment_id, and the last field relates to the ID of a comment record in thewp_cmets` 表。)

我有 810 个没有元数据的 cmets。当我像这样运行脚本时,它处理完 410。当我用 return true 替换 $this->process_comment( $comment_id ); 行时,脚本“处理”所有 810。

process_comment 调用恢复后,我必须运行脚本四次才能处理所有 810 条记录。

  • 第一次,脚本循环6次,处理410条记录。数据库确认还有 400 个。除了循环提前结束的事实之外,这很奇怪,因为 6 批 100 应该是 600。
  • 第二次,它循环了 3 次,处理了 200 条记录,剩下 200 条。所以它完成了 200 条而不是 300 条。
  • 第三次,循环2次,处理100条记录,剩下100条。
  • 第四次循环一次,没有留下任何不变的记录。

很明显,评论元数据的更新导致循环提前结束。我错过了什么明显的东西吗?


编辑

我发现脚本只处理每隔一批的 100 条记录。 ????

【问题讨论】:

    标签: php sql wordpress while-loop


    【解决方案1】:

    啊啊啊!这是偏移量!当我删除它时,脚本会按预期处理所有记录。

    循环的第一次迭代处理了前 100 条记录,将它们从没有元值的记录集中删除。这留下了 710。但是下一次迭代从偏移 100 开始,这意味着这 710 中的前 100 个没有被处理。我不需要偏移量——我只需要每次选择第一批剩余的记录。

    修正后的脚本是

    class Mark_Comments_Reviewed {
    
        public function __invoke() {
    
            $limit  = 100;
    
            while ( $comment_ids = $this->get_unreviewed_comments( $limit ) ) {
                array_walk(
                    $comment_ids,
                    function ( $comment_id ) {
                        $comment_id = (int) $comment_id;
                        $this->process_comment( $comment_id );
                    }
                );
            }
        }
    
        protected function get_unreviewed_comments( int $limit ): array {
    
            global $wpdb;
    
            return $wpdb->get_col(
                $wpdb->prepare(
                    "SELECT DISTINCT comments.comment_ID
                        FROM wp_comments AS comments
                        AND comments.comment_ID NOT IN (
                            SELECT meta.comment_id
                            FROM wp_commentmeta AS meta
                            WHERE meta.meta_key = 'reviewed'
                        )
                        LIMIT %d"
                    $limit
                )
            );
        }
    
        protected function process_comment( int $comment_id ): bool {
            return ! ! update_comment_meta( $comment_id, 'reviewed', (int) true );
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-09
      • 1970-01-01
      • 2018-03-17
      • 2016-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-07
      相关资源
      最近更新 更多