使WordPress成为核心

开的13年前

上次修改时间2个月前

#18408 分配 缺陷(bug)

无法在管理编辑页面中自定义wp_Query后使用wp_reset_postdata

报告人: 埃里克利斯的简介 埃里克利斯 所有者: audrasjb的个人资料 audrasjb公司
里程碑: 未来版本 优先: 正常的
严重程度: 正常的 版本: 4.7.2
组件: 查询 关键词: 需求-测试 has-patch接口 早期的 需求-单元测试
重点: 抄送:

描述

在编辑帖子页面(或任何帖子类型)上,如果在输出编辑器之前创建自定义WP_Query对象,来自自定义WP_Query的帖子数据将填写编辑帖子表单,而不是实际尝试编辑的帖子的原始内容。

我在尝试在“side”上下文中创建自定义元对话框时发现了这一点。您可以通过将此代码插入插件来重现:

add_action(“添加meta_box”,“myplugin_add_custom_box”);函数myplugin_add_custom_box(){添加元数据框(“myplugin_sectionid”,__(“我的帖子标题”,“myplugin_textdomain”),“myplugin_inner_custom_box”,“发布”,“侧面”);}函数myplugin_inner_custom_box(){全球$邮政;$a=新WP_Query('post_type=page');while($a->have_posts()):$a->the_post();endwhile;wp_reset_postdata();}

发生这种情况是因为$wp_query->post从未在管理加载中定义,wp_reset_postdata依赖该加载重置原始post数据。

在定义了$post全局变量之后,我附加了一个定义$wp_query->post的补丁。

附件(6)

后.php(60.2 KB)-添加人埃里克利斯 13年前.
wp-admin/includes/post.php
18408.补丁(1.3 KB)-添加人埃里克利斯 13年前.
.patch文件版本
18408.php(马力)(440字节)-添加人埃里克利斯 9年前.
18408-wp-query-in-admin.php(585字节)-添加人布内博格斯 9年前.
18408.5.diff差异(1.2 KB)-添加人你好_McGee 14个月前.
18408.6差异(772字节)-添加人Howdy_McGee你好 5个月前.
更直接、无挂钩的补丁。

将所有附件下载为:.zip文件

更改历史记录(57)

@埃里克利斯
13年以前

wp-admin/includes/post.php

@埃里克利斯
13年以前

.patch文件版本

#1 @埃里克利斯
13年以前

  • 关键词 需求-测试 开发人员反馈补充

#2 @埃里克利斯
13年以前

  • 分辨率设置为无效
  • 状态已从更改新的关闭

#3 @谢尔盖·比尤科夫
13年以前

  • 里程碑 等待审查删除

#4 @比利里克森
12年以前

为什么设置为无效?我也有同样的问题。

我的解决方案是将原始帖子保存在$original_post中,然后在我的metabox底部放置setup_postdata($original _post);

虽然这样做有效,但能够使用wp_reset_query或wp_leset_postdata会更好。

如果此票证无效,建议使用什么方法在metabox中恢复查询?

#5 @埃里克利斯
12年以前

我将其设置为无效,因为在这种情况下,正确的做法是在后端的任何位置使用get_posts(),而不使用任何模板标记。

#6 @比勒里克森
12年以前

无论使用什么方法生成循环,如果将post数据设置为其他值,则需要重置它。使用get_posts:

$original_post=$post;$myposts=get_posts($args);foreach($myposts作为$post):setup_postdata($post);...每个端点:setup_postdata($original_post);

使用WP_Query(我是如何做的):

$original_post=$post;$loop=新WP_Query($args);while($loop->have_posts()):$loop->the_post();...endwhile;setup_postdata($original_post);

我认为可以合理地假设,在大多数情况下,您都需要访问post数据。

#7 @埃里克利斯
12年以前

Bill-您可以通过foreach循环中的$myposts对象访问所有post数据,而无需使用setup_postdata()作为每个$post的类变量,我相信setup_postdata只会使通过模板标记访问变得更加简单。

我同意你的观点,在元框中使用模板标签会很好,只是为了让事情更干净,少一件要记住的事情。

#8 @比勒里克森
12年以前

啊,我知道了,我从来没有使用过get_posts,所以只是基于codex页面的示例。

尽管如此,我仍然认为这是一个合理的投诉。

#9 @错误的
10年以前

  • 组件已从更改编辑器选项,Meta API
  • 分辨率 无效删除
  • 状态已从更改关闭重新打开的
  • 版本已从更改3.2.13.8.1

这不是无效的。我能够在3.8.1中复制这一点。在元框中使用显式WP_Query对象时,无论您尝试什么,都无法在循环后重置postdata。任何后续的元框都将global$post标识为自定义查询的最后一个post。

@ericlewis断言WP_Query和template标记不应在WP-admin中使用,但在我能找到的Codex中或核心贡献者的任何帖子中都没有记录。在WP-admin post屏幕中使用显式创建WP_Query对象的多个循环应该与任何其他查询方法或函数一样工作。

这导致其他插件出现问题,这些插件注册元框并生成支持票证,如下所示:http://wordpress.org/support/topic/plugin-wordpress-seo-by-yoast-after-update-it-wont-save-so?replies=32
在尝试为WP SEO保存帖子元后,我确定了这里提到的支持示例,但更新后出现的元是基于前一个元框中自定义查询中最后一篇帖子的帖子ID。在幕后查看之后,元数据实际上被正确保存到了原始帖子ID中,因为它已经是DOM中的一个表单选项。

使用get_posts代替新的WP_Query是可行的,但这只是应用了一个创可贴修复程序,而这应该是现成的。我认为这需要解决,而不是说“使用另一种查询方法”。插件作者将继续在元框中使用WP_Query,它将继续为后续页面加载中断主查询。

#10 @纳金
10年以前

  • 里程碑设置为等待审查

#11 @布内博格斯
10年以前

  • 组件已从更改选项,Meta API查询

#12 @布内博格斯
9年以前

这仍然是一个问题吗?我不知道如何复制它。当注册包含WP_查询使用ericlewis提供的代码,post.php上的编辑帖子表单将填充预期帖子中的数据。也许我做错了?

#13 @埃里克·刘易斯
9年以前

2011年,右侧边栏在主标题/内容之前以标记形式输出。在过去三年的某个时候(可能是在mp6?期间),这个bug已经被切换了,所以现在bug并没有那么清晰地表达出来。

请参见附件:18408.php,这清楚地表明标题(_T)之后wp_reset_postdata()正在使用来自自定义WP_Query的数据,而不是要编辑的原始帖子。

#14 @布内博格斯
9年以前

  • 关键词 第二个小齿轮补充;开发人员反馈远离的

谢谢ericlewis。现在我明白了。

根本问题是wp_reset_postdata()旨在重置全局变量以匹配主查询。但对于post.php,没有主查询-$帖子全局使用手动填充获取post()而不是通过正常$wp_query循环。因此,解决这个问题最直接的方法可能是通过执行“真实”$wp_query在edit.php上循环。请参见18408-wp-query-in-admin.php。这与您最初的修改建议类似获取默认设置post_to_edit(),但目标更明确。

这个解决方案的优点是工作包查询(_Q)edit.php上的实例现在的工作方式与WP_查询其他任何地方的实例。糟糕的是,这有点武断。在前端,WP引导过程(请特别参阅WP::main())根据从URL解析出的查询变量启动主WP查询。如果我们像我在补丁中建议的那样在post.php上伪造它,我们只复制了这个过程的一部分,这可能会导致其他一些混乱。(例如,如果您看到$wp_query全球,您还希望找到一个$wp->matched_rule($wp->matched_rule)?)

建议的药物可能会有奇怪的副作用$wp_query覆盖-我想,特别是如果元框以某种有趣的方式操纵全局。这就是说,我很难想出任何可能破坏的现实例子。

其他人怎么想?

#15 @布雷特舒马克
9年以前

我刚刚遇到了这种不一致,因为我有一个插件,它正在管理栏中做一些事情。最初,它只是拉一个页面列表并将其编辑链接添加到管理栏项目,但我有一个功能请求,要求能够向该项目添加其他帖子类型。我是和WP_查询但发现它打破了编辑屏幕,因为可编辑的内容是从管理栏中我的项目列表中的最后一篇文章中提取的。我以为是这样wp_reset_postdata()起初没有正常工作,但后来意识到发生了什么。

我同意@boonebgorges和@misternifty的观点,即需要修复此问题,以便主查询行为在整个管理区域内保持一致。这对WP_查询处理一些页面,但不是所有页面。

#16 @德齐奥1900
9年以前

当我试图更改“wp_before_admin_bar_render”动作挂钩中的工具栏项时,也遇到了同样的错误。我想在工具栏中添加一个自定义类型的帖子,当然我使用了WP_Query,但这导致了这个错误出现在帖子编辑屏幕上。

我最终使用了“get_posts”而不是“WP_Query”,这解决了问题。但是这个错误是不可接受的,应该修复!

#17 随访: @布内博格斯
9年以前

  • 里程碑已从更改等待审查未来版本

#18 答复: 17 @执政官810
9年以前

回复布内博格斯以下为:

那么FutureRelease——这是否意味着修复已经到位,正在等待下一个版本?这是一个4岁的小虫子,我们只是浪费了几个小时才发现这张罚单。

#19个 @巴里切伦
9年以前

这种行为也让我有些抓耳挠腮。向添加了注释http://codex.wordpress.org/Class_Reference/WP_查询.

#20 @美妙的男孩音乐
9年以前

  • 关键词 关闭补充;第二个小齿轮远离的

我无法想象如果我们这样做了会发生什么:

全局$wp_query;if(isset($wpquery)){$wp_query->reset_postdata();}其他{//一定会打破无数插件和主题的代码}

全球是超级脆弱的。我认为我们不应该在这个屏幕上通过主动重置来积极支持主题函数和嵌套循环。你最好切换全局$帖子在您自己的代码中。

#21 @美妙的男孩音乐
9年以前

  • 关键词 不间断的补充;关闭远离的

这可能是更大讨论的一部分。我还想让EAL的第一个错误报告永垂不朽。

#22 随访: @匈牙利
8年以前

  • 关键词 需要-补丁补充;has-patch接口远离的
  • 版本 3.8.1删除

我只是在版本4.4.1中遇到了这个问题,想知道它是怎么回事?必须将meta_box中的$context更改为“normal”或保留默认设置“advanced”。

#23 答复: 22 @Mekku公司
8年以前

回复匈牙利以下为:

我只是在版本4.4.1中遇到了这个问题,想知道它是怎么回事?必须将meta_box中的$context更改为“normal”或保留默认设置“advanced”。

我的临时解决方案是在注册元框的同一函数/方法中添加以下代码:

//修复全局$post,$wp_query;$wp_query->post=$post;//添加元框添加元数据框(…)添加元数据框(…)

#24个 答复:说明;随访: @五452
7年以前

  • 版本设置为4.7.2

你知道这件事吗?我也遇到过类似的情况。

我正在尝试用自定义帖子类型的标题填充元对话框下拉列表。
将保存此数据的帖子也是一个自定义帖子类型。

如果不使用wp_query并对选项进行硬编码,它可以很好地工作,但当我使用wp_ query时,在保存时会出现问题。它填充下拉列表,但永久链接已更改,下拉列表已重置/无法保存。它有时也会影响标题。

#25 答复: 24;随访: @杰普·西姆金斯
7年以前

要绕过此问题,请不要使用_支柱因为这是问题所在。

我使用这种语法,并且我有许多元对话框,对默认post对象没有问题,也不需要调用wp_reset_postdata();.

<?php(电话)
$查询 = 新的 \WP_查询($个参数);
如果 ($查询->有立柱(_P)()) {
    foreach公司 ($查询->获取文章(_P)() 作为 美元) {
        //使用$p作为普通WP_Post对象的普通循环逻辑    }
}

需要注意的是,不能使用以下循环方法获取标题()但你可以很容易地打电话$p->帖子标题。我不认为过滤器应用于这些对象,因此您可能需要为后端使用与前端不同的对象,因为该问题仅出现在WP的后端。

此外,您可以将相同的参数与获取posts();

上次编辑时间7年前通过杰普·西姆金斯(以前的)(差异)

#26 答复: 25;后续行动: @尼特斯·卢哈鲁卡
7年以前

这工作得很好。4.7.4中也存在此问题。

回复杰普·西姆金斯以下为:

要绕过此问题,请不要使用_支柱因为这是问题所在。

我使用这种语法,并且我有许多元对话框,对默认post对象没有问题,也不需要调用wp_reset_postdata();.

<?php(电话)
$查询 = 新的 \WP_查询($个参数);
如果 ($查询->有立柱(_P)()) {
    foreach公司 ($查询->获取文章(_P)() 作为 美元) {
        //使用$p作为普通WP_Post对象的普通循环逻辑    }
}

需要注意的是,不能使用以下循环方法获取标题()但你可以很容易地打电话$p->帖子标题。我不认为过滤器应用于这些对象,因此您可能需要为后端使用与前端不同的对象,因为该问题仅出现在WP的后端。

此外,您可以将相同的参数与获取posts();

#27 答复: 26 @拉格驴
7年以前

可以确认在Wp 4.8.1中,此问题仍然存在。让我注意到的是,在保存时,当前编辑的帖子/页面的slug正在更改,以匹配我在帖子编辑器中运行的Wp_query中最后一篇帖子的slugl。我的元框在编辑器的侧边栏部分被挂入低优先级。

特别奇怪的是,如果你做了这样的事情

<?php(电话)
获取标题(美元->身份证件);
?>

然后你就得到了期望的结果。

这个解决方案挽救了我的生命,但问题本身花费了我大约一个小时的调试时间,试图找出问题的根源。问题发生在我的本地Apache托管的开发环境中,没有插件,只有我正在处理的自定义主题。如果它真的有帮助的话,我还注意到了wp后端的其他区域在处理自定义wp_query时出现的问题,最引人注目的是其他插件,如高级自定义字段。

回复尼特斯·卢哈鲁卡以下为:

这工作得很好。问题在4.7.4中仍然存在。

回复杰普·西姆金斯以下为:

要绕过此问题,请不要使用_支柱因为这是问题所在。

我使用这种语法,并且我有许多元对话框,对默认post对象没有问题,也不需要调用wp_reset_postdata();.

<?php(电话)
$查询 = 新的 \WP_查询($个参数);
如果 ($查询->有立柱(_P)()) {
    foreach公司 ($查询->获取文章(_P)() 作为 美元) {
        //使用$p作为普通WP_Post对象的普通循环逻辑    }
}

需要注意的是,不能使用以下循环方法获取标题()但你可以很容易地打电话$p->标题。我不认为过滤器应用于这些对象,因此您可能需要为后端使用与前端不同的对象,因为该问题仅出现在WP的后端。

此外,您可以将相同的参数与获取posts();

上次编辑时间7年前通过拉格驴(以前的)(差异)

#28 @海洋90
7年以前

#41958被标记为副本。

#29 @比利里克森
5年以前

WordPress 5.0的经典编辑器和块编辑器中仍然存在此问题。

您可以使用此插件重现问题:https://gist.github.com/billerickson/21ff280fb26c3b98120044d53f4e1b61

经典编辑器屏幕截图:https://cl.ly/e122cffed719
块编辑器屏幕截图:https://cl.ly/33bd55ca2869

这也导致了古腾堡区块的问题(参见https://github.com/WordPress/gutenberg/issues/7468),并使用上面概述的相同方法临时修复-备份全局$post,然后恢复(请参阅https://github.com/WordPress/gutenberg/pull/7889).

#30 @史密里曼
4年以前

这个问题非常令人沮丧,影响了很多插件。例如,Yoast SEO在恢复修订时处理短代码,这可能会导致在恢复修订后重定向到错误的页面。

他们不想修复它,因为这是WordPress的核心问题:https://github.com/Yoast/wordpress-seo/issues/12017

上述方法建议建立一个完整的WP_查询管理页面上的循环,我可以想象这可能很棘手。

与其在所有插件和大量其他位置添加黑客代码,以便在每次可能更改$post变量时备份和保存它,不如只做一次?什么时候?$帖子首先在admin中创建,保存它;然后调整wp_reset_postdata如果你在管理员中,可以使用函数来恢复它。

这样插件/短代码可以继续使用wp_reset_postdata以正常的方式。

#31 @Howdy_McGee你好
3年以前

在管理面板中全局$wp_query技术上仍然可以使用。我们可以简单地存储全球$帖子循环启动设置特定标志时挂起(is_admin()? ):

add_action('loop_start',function(){如果(!is_admin()){回报;}全球$帖子,$wp_query;$wp_query->post=$post;} );

上面是一个简单的示例,但它看起来像全局$wp_query在大多数(如果不是所有的话)管理面板请求中保持为空。这样就可以使用辅助WP_Querys和wp_reset_postdata().我们这样做会遇到任何可预见的问题吗?

上次编辑时间3年前通过Howdy_McGee你好(以前的)(差异)

#32 @Howdy_McGee你好
3年以前

#30273被标记为副本。

#33 @史密里曼
3年以前

我只是想在这里加入一个额外的想法。我一直认为这是WordPress的核心错误wp_reset_postdata是快捷代码、动态块或管理代码运行自己的自定义查询的正确方式。

然而,我最近发现,受调用影响的不仅仅是WordPress管理员。例如,如果完全普通的主题代码运行自定义循环并调用,Exchange(_E)(为空,因此处理完整内容以生成自动内容,并可能运行短代码等)$帖子变量也被破坏,因为它被重置为不正确的值。

这里的真实情况是根本没有管理错误吗?实际上,在管理中使用任何短代码、动态块或自定义代码都是不正确的wp_reset_postdata首先?(使用比尔·埃里克森的解决方案-保存邮政编码$变量,然后恢复它-正确的编码方法?)

上次编辑时间3年前通过史密里曼(以前的)(差异)

#34 @史密里曼
3年以前

对不起,忽略以上内容。刚刚意识到摘录会删除块和短代码,所以它毕竟不会影响前端。

#35个 @Howdy_McGee你好
14个月以前

  • 关键词 has-patch接口补充;需要-补丁远离的

此修补程序允许开发人员使用wp_rest_postdata().

这张票是在松弛(Slack)howdymcgee的#core。查看日志.


13个月以前

#37 @谢尔盖·比尤科夫
13个月以前

  • 里程碑已从更改未来版本6.3

这张票是在松弛(Slack)howdymcgee的#core。查看日志.


13个月以前

#39个 @hellofrom托尼亚
13个月以前

  • 关键词 早期的补充

由于此票据建议更改WP_查询全球,承诺应该实现早期的在开发周期中允许更长的时间进行测试和反馈。

这张票是在松弛(Slack)audrasjb的in#core。查看日志.


11个月以前

#41 @audrasjb公司
11个月以前

  • 所有者已从更改埃里克利斯audrasjb公司
  • 状态已从更改重新打开的分配

按照今天的虫子清理。
提议的补丁仍需测试。重新分配给自己。

#42 @audrasjb公司
11个月以前

  • 关键词 需求-单元测试补充;不间断的远离的

这可能也需要一些单元测试。

这张票是在松弛(Slack)audrasjb的in#core。查看日志.


11个月以前

#44 @audrasjb公司
11个月以前

  • 里程碑已从更改6.36.4

根据今天的漏洞清理,我们将把它提升到里程碑6.4、待定的单元测试和手动测试。

这张票是在松弛(Slack)oglekler的in#core。查看日志.


8个月以前

#46 @奥格勒克勒
8个月以前

嗨,@Howdy_McGee,这张票是在bug清理期间审核的。由于可能产生的影响,它需要尽早完成,还需要进行单元测试,另外测试人员需要一个如何检查它的说明。你能继续吗?谢谢你🙏

同时添加道具:@hellofromTonya@zunaid321

#47 @奥勒克勒
7个月以前

  • 里程碑已从更改6.46.5

因为这是一张早票,我将把它推进6.5里程碑。如果没有进展,下次应该重新安排到未来版本。

这张票是在松弛(Slack)abhanonstopnews的incore。查看日志.


5个月以前

#49 @奥格勒克勒
5个月以前

这张罚单是在除虫期间讨论的。

它仍然需要单元测试和测试说明。因为这是一张早期的门票,所以决定在Dev聊天中突出显示它。

将道具添加到@webcommsat

@Howdy_McGee你好
5个月以前

更直接、无挂钩的补丁。

#50个 @Howdy_McGee你好
5个月以前

最新的补丁摆脱了基于hook的方法,直接将关联添加到post.php。这应考虑以下情况:

  • 使用不推荐的query_posts()和wp_reset_query()直接重写查询
  • 使用WP_Query()和WP_reset_postdata()进行辅助查询
  • 全局发布使用setup_postdata($post)和wp_reset_postdta()覆盖。

我同意@oglekler的观点,即在添加单元测试之前,应该将其移到未来版本。

#51 @audrasjb公司
2个月以前

  • 里程碑已从更改6.5未来版本

正在移至未来版本,待定的单元测试。

注:请参见TracTickets公司有关使用的帮助门票。