Php 选中父类别时自动检查子类别/术语
我有这个大陆->国家类别设置为一个自定义的职位类型Php 选中父类别时自动检查子类别/术语,php,wordpress,Php,Wordpress,我有这个大陆->国家类别设置为一个自定义的职位类型 - Africa - Uganda - Zambia - Zimbabwe - Asia - Afghanistan - Bahrain - Bangladesh - Bhutan 我认为这可以通过某种WordPress功能来解决,如果父类别Africa被选中,该功能将自动检查一个大陆的所有子类别国家,而不是像plugin那样的其他方式 例如,如果选中非洲,则应自动选中所有非洲国家。如果
- Africa
- Uganda
- Zambia
- Zimbabwe
- Asia
- Afghanistan
- Bahrain
- Bangladesh
- Bhutan
我认为这可以通过某种WordPress功能来解决,如果父类别Africa被选中,该功能将自动检查一个大陆的所有子类别国家,而不是像plugin那样的其他方式
例如,如果选中非洲,则应自动选中所有非洲国家。如果仅选中津巴布韦,则不应选中父类别Africa
此外,如果未选中非洲,非洲国家也应自动取消选中。编辑:
我有一个相对较长的答案,可以很好地检查子术语,但在父母未检查时取消检查它们就不太好了。我在这里支持这个答案:也可以在
新答案:
好吧,事实上我为这个结果感到很自豪。在做了一些研究之后,我发现了钩子,它在函数的末尾被激发,位于
在这个钩子上,它接受6个参数:$object\u id、$terms、$tt\u id、$taxonomy、$append、$old\u tt\u id。这里对于check子项和uncheck子项来说,重要的是$tt_id和$old_tt_id。这些分别是新术语ID和旧术语ID的数组
这使我们能够比较这两个阵列,并查看添加了哪些ID以及删除了哪些ID。这一点很重要,因为你可以选择非洲,然后取消选择非洲,现在选择亚洲。这里有一个方便的函数,可以让您看到这两种差异:
function array_diff_once($a1, $a2){
foreach($a2 as $val){
if( false !== ($pos = array_search($val, $a1)) ){
unset($a1[$pos]);
}
}
return array_values($a1);
}
因此,我们不必使用save_post钩子,而是可以比较set_object_terms钩子上添加/删除的术语,并为每个术语添加/删除子术语。注意,如果帖子没有发布,在不合适的时候自动保存,等等,这也会触发,所以我设置了一些中止条件
add_action( 'set_object_terms', 'so_60079535_toggle_child_terms', 10, 6 );
function so_60079535_toggle_child_terms( $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids ){
// Abort if this is an autosave/backup
if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
return;
// Abort if no ids are set from before or now
if( empty($tt_ids) && empty($old_tt_ids) )
return;
// Only do things if this post is published (front facing)
$post_status = get_post_status( $object_id );
if( $post_status != 'publish' )
return;
// What terms where ADDED, and which were REMOVED?
$added_terms = array_diff_once( $tt_ids, $old_tt_ids );
$removed_terms = array_diff_once( $old_tt_ids, $tt_ids );
// Any terms ADDED this time?
if( !empty($added_terms) ){
foreach( $added_terms as $added_term ){
// Do any of these added terms have children?
if( $added_child_terms = get_term_children( $added_term, $taxonomy ) ){
// Append those children
wp_set_object_terms( $object_id, $added_child_terms, $taxonomy, true );
}
}
}
// Any terms REMOVED?
if( !empty($removed_terms) ){
foreach( $removed_terms as $removed_term ){
// Do any of the removed terms have children?
if( $removed_child_terms = get_term_children( $removed_term, $taxonomy ) ){
// Remove them all
wp_remove_object_terms( $object_id, $removed_child_terms, $taxonomy, true );
}
}
}
}
事实上,我已经把这段代码放在了我的测试站点上,它似乎工作得完美无缺,不管孙子/大孙子术语有多深,一次添加或删除了多少。另一件巧妙的事情是,这个钩子已经传递了$taxonomy参数,因此它应该可以自动地用于任何和所有添加的分类法。如果不希望这样做,您可以随时非常轻松地为某些分类法、帖子类型等添加中止条件。编辑:
我有一个相对较长的答案,可以很好地检查子术语,但在父母未检查时取消检查它们就不太好了。我在这里支持这个答案:也可以在
新答案:
好吧,事实上我为这个结果感到很自豪。在做了一些研究之后,我发现了钩子,它在函数的末尾被激发,位于
在这个钩子上,它接受6个参数:$object\u id、$terms、$tt\u id、$taxonomy、$append、$old\u tt\u id。这里对于check子项和uncheck子项来说,重要的是$tt_id和$old_tt_id。这些分别是新术语ID和旧术语ID的数组
这使我们能够比较这两个阵列,并查看添加了哪些ID以及删除了哪些ID。这一点很重要,因为你可以选择非洲,然后取消选择非洲,现在选择亚洲。这里有一个方便的函数,可以让您看到这两种差异:
function array_diff_once($a1, $a2){
foreach($a2 as $val){
if( false !== ($pos = array_search($val, $a1)) ){
unset($a1[$pos]);
}
}
return array_values($a1);
}
因此,我们不必使用save_post钩子,而是可以比较set_object_terms钩子上添加/删除的术语,并为每个术语添加/删除子术语。注意,如果帖子没有发布,在不合适的时候自动保存,等等,这也会触发,所以我设置了一些中止条件
add_action( 'set_object_terms', 'so_60079535_toggle_child_terms', 10, 6 );
function so_60079535_toggle_child_terms( $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids ){
// Abort if this is an autosave/backup
if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
return;
// Abort if no ids are set from before or now
if( empty($tt_ids) && empty($old_tt_ids) )
return;
// Only do things if this post is published (front facing)
$post_status = get_post_status( $object_id );
if( $post_status != 'publish' )
return;
// What terms where ADDED, and which were REMOVED?
$added_terms = array_diff_once( $tt_ids, $old_tt_ids );
$removed_terms = array_diff_once( $old_tt_ids, $tt_ids );
// Any terms ADDED this time?
if( !empty($added_terms) ){
foreach( $added_terms as $added_term ){
// Do any of these added terms have children?
if( $added_child_terms = get_term_children( $added_term, $taxonomy ) ){
// Append those children
wp_set_object_terms( $object_id, $added_child_terms, $taxonomy, true );
}
}
}
// Any terms REMOVED?
if( !empty($removed_terms) ){
foreach( $removed_terms as $removed_term ){
// Do any of the removed terms have children?
if( $removed_child_terms = get_term_children( $removed_term, $taxonomy ) ){
// Remove them all
wp_remove_object_terms( $object_id, $removed_child_terms, $taxonomy, true );
}
}
}
}
事实上,我已经把这段代码放在了我的测试站点上,它似乎工作得完美无缺,不管孙子/大孙子术语有多深,一次添加或删除了多少。另一件巧妙的事情是,这个钩子已经传递了$taxonomy参数,因此它应该可以自动地用于任何和所有添加的分类法。如果不希望这样做,您可以随时为某些分类法、帖子类型等添加中止条件,非常容易。找到自定义帖子分类法名称,将其替换为“category”。当选择非洲时,所有非洲国家都被选中-完美!唯一的问题是当取消选择非洲时,非洲国家仍然被选中,该功能如何恢复?很抱歉,这比我想象的要大,所以我不得不在午餐休息时处理它-但我想我找到了一个解决方案,它将完全按照您所描述的方式工作!我已经更新了答案并备份了旧的答案-看一看,让我知道!我添加了$taxonomy='custom_post_type';开始时限制自定义帖子类型。你做得很好,非常感谢!找到自定义帖子分类名称,将其替换为“category”。当选择非洲时,所有非洲国家都被选中-完美!唯一的问题是当取消选择非洲时,非洲国家仍然被选中,如何恢复此功能?抱歉,这比我想象的要大,所以我没有 o在我午餐休息的时候做这件事-但我想我找到了一个解决方案,它将完全按照你所描述的方式工作!我已经更新了答案并备份了旧的答案-看一看,让我知道!我添加了$taxonomy='custom_post_type';开始时限制自定义帖子类型。你做得很好,非常感谢!