为什么Get_Category_by_slug()会导致WordPress 4.8崩溃

时间:2017-08-06 作者:That Brazilian Guy

我需要从可选择的帖子类别列表中隐藏“未分类”,并编写一些代码来实现这一点。This function worked fine 在WP 4.7.5之前,成功隐藏了以下类别:

add_filter(\'list_terms_exclusions\', \'myproject_hide_uncategorized\',1);
function myproject_hide_uncategorized( $exclude_query ) {
  if (function_exists(\'get_current_screen\')) {
    $currentScreen = get_current_screen();

    if ($currentScreen->base == \'post\') {
      $newquery = "";
      $excluidos = array();
      $excluidos[] = get_category_by_slug(\'sem-categoria\')->cat_ID;
      $excluidos[] = get_category_by_slug(\'uncategorized\')->cat_ID;
      foreach ($excluidos as $excluido) {
        $newquery .= " AND t.term_id <> \'$excluido\' ";
      }
      $exclude_query .= $newquery;
    }
  }
  return $exclude_query;
}
然而,在更高版本(4.8.1是目前为止的最新版本)上,每当我尝试编辑帖子或创建新帖子(访问“localhost/wp admin/post new.php”),我都会收到以下错误消息:

Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 130968 bytes) in /var/www/html/wp-includes/class-wp-term-query.php on line 294

提高内存限制只会导致超时错误。我能够在WP 4.8和4.8.1的干净安装中复制该行为

看起来崩溃是由这四条线引起的,将其添加到functions.php 任何主题的文件似乎都会导致崩溃:

add_filter(\'list_terms_exclusions\', \'this_will_crash_wordpress\');
function this_will_crash_wordpress( $exclude_query ) {
  get_category_by_slug(\'uncategorized\');
}

What changed between 4.7.5 that causes this error? How can I make it go away? Do I have to rewrite my code? If so, how?

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

因为get_category_by 呼叫get_term_by 哪个呼叫get_terms 这将创建WP_Term_Query 运行list_terms_exclusions 过滤器,它运行调用get_category_by 哪个呼叫get_term_by 哪个呼叫get_terms 等等等等等等

Your problem is that of an infinite loop, 您在过滤器中调用的函数会触发它们被调用的过滤器。并不是WordPress发生了变化,而是过滤器一开始就不应该工作。

解决方案

断开环路

在调用之前,请解开过滤器get_category_by, 然后再把它钩住。

我不太喜欢这个选项

从术语ID更改为术语slug/name

您不需要找到具有名称的术语IDuncategorized, 您已经传入了SQL,所以请使用t.slug <> \'uncategorized\' 或者类似的东西

这稍微好一点,但它仍然犯了一个基本的错误,即为MySQL提供了一个NOT选择器。这些类型的查询基本上很昂贵,而且无法扩展,您应该询问您想要什么,而不是不想要什么。

在PHP中提取术语

提取术语后,在PHP中手动提取不需要的术语。这是性能最好的选项,可扩展性最好。它对数据库更加友好

该metabox专门使用以下两个函数来显示术语:

  • wp_dropdown_categories
  • wp_terms_checklist
wp_dropdown_cats 可用于筛选的最终HTML输出wp_dropdown_categories 虽然你可以get_terms 并使用其过滤器更有效地删除该点之前的项。For details on how to do that, see this question/answer

这是我首选的解决方案

删除metabox并添加自己的

只要表单输入与标准metabox相同,就可以完全替换它,并且不需要保存代码。

我不太喜欢这个解决方案,因为它可能会干扰其他插件,并且需要付出最大的努力

结束

相关推荐

如何使用Dashboard_Glance_Items挂钩使帖子和评论不可点击

我有一个多作者网站,我已经使用了一些挂钩来阻止他们查看其他作者的帖子和媒体。现在,在“概览”部分的Wordpress仪表板中,它向他们显示了全部帖子和评论。他们现在可以点击他们,我希望他们不能这样做。所以,我找到了一个针对这个的钩子,虽然我才刚刚开始学习如何使用钩子进行定制,所以我需要一些帮助。下面是我现在所拥有的,只是回显当前用户的ID以验证它是正确的钩子:add_filter(\'dashboard_glance_items\', \'make_unclickable\'); fun