Because get_category_by
calls get_term_by
which calls get_terms
which creates a WP_Term_Query
which runs the list_terms_exclusions
filter, which runs your code that calls get_category_by
which calls get_term_by
which calls get_terms
etc etc etc
Your problem is that of an infinite loop, the functions you call in your filter, trigger the filter they’re called in. It’s not that WordPress has changed, but rather that the filter should never have worked to begin with.
Solutions
Breaking The Loop
Unhook your filter before calling get_category_by
, then hook it back in afterwards.
I’m not a big fan of this option
Changing from term ID to term slug/name
You don’t need to find which term ID has the name uncategorized
, you’re already passing in SQL, so use t.slug <> 'uncategorized'
or something to that effect
This is a bit better, but it still commits the fundamental sin of giving a NOT selector to MySQL. Those kinds of queries are fundamentally expensive and don’t scale, you should ask for what you want, not what you do not want.
Pulling the term out in PHP
When the terms are fetched, manually take out the term you don’t want in PHP afterwards. This is the most performant options, and scales the best. It’s also much more database friendly
That metabox specifically uses these 2 functions to display the terms:
wp_dropdown_categories
wp_terms_checklist
wp_dropdown_cats
can be used to filter the final HTML output of wp_dropdown_categories
although you could reach into get_terms
and use its filters to remove the term before that point more efficiently. For details on how to do that, see this question/answer
This is my preferred solution
Remove the metabox and add your own
As long as the form inputs are the same as the standard metabox, you can replace it entirely, and there’ll be no need for save code.
I’m not a big fan of this solution as it could interfere with other plugins and has the largest effort required