php - 为什么这个`while`循环在更改数据时不处理所有记录?
问题描述
我while
在 WordPress 脚本中有一个 PHP 循环,当它修改数据时,它似乎只处理了它应该处理的一半记录,我很难理解为什么会发生这种情况。
我正在编写一个 WP-CLI 脚本,它将在所有尚未拥有它的评论上设置一个带有键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_id
,meta_key,
meta_value and
comment_id , and the last field relates to the ID of a comment record in the
wp_comments`表。)
我有 810 条没有元数据的评论。当我像这样运行脚本时,它完成了 410 的处理。当我用 替换该$this->process_comment( $comment_id );
行时return true
,脚本“处理”所有 810。
通话恢复后process_comment
,我必须运行脚本四次才能处理所有 810 条记录。
- 第一次,脚本循环 6 次,处理 410 条记录。数据库确认还有 400 个。除了循环提前结束的事实之外,这很奇怪,因为 6 批 100 应该是 600。
- 第二次,它循环了 3 次,处理了 200 条记录,剩下 200 条。所以它完成了 200 条而不是 300 条。
- 第三次,它循环了 2 次,处理了 100 条记录,剩下 100 条。
- 第四次它循环一次并且没有留下任何不变的记录。
显然,评论元数据的更新导致循环在它应该完成之前完成。我错过了一些明显的东西吗?
编辑
我发现脚本只处理每隔一批的 100 条记录。
解决方案
啊啊啊!这是偏移量!当我删除它时,脚本会按预期处理所有记录。
循环的第一次迭代处理了前 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 );
}
}
推荐阅读
- aws-nuke - 如果 aws-nuke 大多失败,如何对 aws 进行核攻击
- r - 如何订购分组箱线图?
- python - 无法通过任何方法通过 Speech_recognition python 获取音频?
- react-native - 如何在本机反应中添加显示更多和显示更少按钮并根据它们呈现项目
- r - Shiny R:需要相互更新的两个 selectizeInput 菜单(互斥选择)
- nuxt.js - 使用 nuxtjs 部署到 Netlify 的错误
- typescript - 缩小打字稿中的generec类型
- java - 带有 Bootstrap 和 Thymeleaf 页面装饰的 SpringMVC
- php - 用于博客内容的 Home.php 无法检索页面标题 - Wordpress
- java - Android Studio Fragments 和 Adapter 没有连接