如何根据另一个 select 的值过滤 select 结果

How to filter select result based on another select's value

在我的 WordPress 主题中,我有一个名为 Segments 的自定义 post 类型,其中包含两个使用 ACF 制作的自定义字段。我想要实现的是根据第一个字段的值进行第二个字段的搜索。

第一个称为 emission,该字段的类型是将段 post 链接到排放分类法的分类法。

第二个称为剧集,字段类型是 post_object,它将片段 post 链接到剧集 post 类型。

现在,我想要的是第二个字段,用于过滤与第一个字段的所选值具有相同发射值的剧集。

我遇到的问题是,我无法在不保存段的情况下获取第一个字段的值。这是我尝试过的:

add_filter('acf/fields/post_object/query/key=field_57503ed5193d6', array($this, 'show_episodes'), 10, 3);

/*
* Function to show episodes that are from the same program as the current segment.
*/
public function show_episodes($args, $field, $post_id){
    error_log('Post Id: ' . $post_id);
    error_log(json_encode(get_field_object('emission')));
    error_log(json_encode(get_field('emission', $post_id)));

    return $args;
}

当我为一个已经保存的段调用它时,它返回保存的发射值,这是合乎逻辑的,因为它是保存在数据库中的值。当我为一个新的段调用它时,它不起作用,因为它没有保存在数据库中的值,因此,它 returns a null。每当我编辑已保存段的排放值时,它仍然是 returns 旧的排放值(来自数据库的值)。

我已经能够使用 Ajax 和 PHP 会话获得结果。这是我所做的:

Javascript

// The id of the emission field generated by ACF
this.emissionField = $('#acf-field_57473a3f32f6d-input');

if(this.emissionField.length){
    let programId = this.emissionField.val();

    // Update the program id on page load if it's not empty, otherwise hide the emission box
    if(programId != ""){
        this.updateEpisodeFilter(this.emissionField.val());
    }else if(this.episodeBox.length) this.episodeBox.hide();

    // Update the program id when the emission change
    this.emissionField.on('change', function(){
        // Clear the select on value change
        $('#s2id_acf-field_57503ed5193d6-input').select2('val', '');

        this.updateEpisodeFilter(this.emissionField.val());
    }.bind(this));
}

/*
* Function to update the program id in the session.
*/
updateEpisodeFilter(programId){
    let episodeBox = this.episodeBox;

    $.ajax({
        url: '/wp-admin/admin-ajax.php',
        type: 'POST', 
        data:{
            action: 'update_filter_episodes',
            postId: $('#post_ID').val(),
            programId: programId,
        },
        success: function(response){
            if(response && episodeBox.length) episodeBox.show();
        }
    });
}

PHP

// Add the action hook for the Ajax
add_action('wp_ajax_update_filter_episodes', 'update_filter_episodes');
add_action('wp_ajax_admin_update_filter_episodes', 'update_filter_episodes');

因此,当我们通过 Ajax 接收到操作 filter_episodes 时,它会调用 PHP 函数 update_filter_episodes

/*
* Function to update the program id for the episodes filter.
*/
public function update_filter_episodes(){
    $this->startSession();
    if(isset($_POST['postId']) && isset($_POST['programId'])){
        $_SESSION['post-' . $_POST['postId'] . '-emission-id'] = $_POST['programId'];
        wp_send_json(true);
    }
    wp_send_json(false);
}

startSession 函数检查会话是否已经启动:

/*
* Function to start the session if it's not already started.
*/
protected function startSession(){
    if(session_status() != PHP_SESSION_ACTIVE)
        @session_start();
}

要更新 ACF 调用的查询,我们需要另一个钩子来调用函数 show_episodes:

add_filter('acf/fields/post_object/query/key=field_57503ed5193d6', 'show_episodes', 10, 3);

/*
* Function to show episodes that are from the same show as the current segment.
*/
public function show_episodes($args, $field, $post_id){
    $this->startSession();

    $index = 'post-' . $post_id . '-emission-id';
    if(isset($_SESSION[$index]) && !empty($_SESSION[$index]))
        $args['tax_query'] = array(array('taxonomy' => 'category', 'terms' => $_SESSION[$index]));

    return $args;
}

不确定这是否是最简单的方法,但它对我有用。但是,如果有人有更好的解决方案,请随时告诉我!