用于合并两个分类法的自定义SQL查询


Custom SQL Query to merge two taxonomies

我是SQL+PHP的新手,我想在一个插件中添加一个函数,一切都很好,除非这个问题。

链接到我的网页

我有两个下拉列表,其中一个具有相应的分类法。它应该在两个下拉列表之间搜索匹配的结果,但这没有发生,我可以搜索一个或另一个下拉列表/分类法。

此操作的代码如下

public function find_nearby_locations() {
        global $wpdb, $wpsl, $wpsl_settings;
        $store_data = array();
        /* Set the correct earth radius in either km or miles. 
         * We need this to calculate the distance between two coordinates. 
         */
        $radius = ( $wpsl_settings['distance_unit'] == 'km' ) ? 6371 : 3959; 
        /* The placeholder values for the prepared statement in the sql query. */
        $placeholder_values = array(
            $radius,
            $_GET['lat'], 
            $_GET['lng'], 
            $_GET['lat']
        );
        /* Check if we need to filter the results by category. */
        if ( isset( $_GET['filter'] ) && $_GET['filter'] ) {
            $placeholder_values[] = $_GET['filter'];

            $cat_filter =
            "INNER JOIN $wpdb->term_relationships AS term_rel ON posts.ID = term_rel.object_id
             INNER JOIN $wpdb->term_taxonomy AS term_tax ON term_rel.term_taxonomy_id = term_tax.term_taxonomy_id
             AND (term_tax.taxonomy = 'wpsl_store_category' OR term_tax.taxonomy = 'wpsl_custom_category') AND term_tax.term_id = %d";



        } else {
            $cat_filter = '';
        }
        /** 
         * If WPML is active we include 'GROUP BY lat' in the sql query
         * to prevent duplicate locations from showing up in the results.
         *  
         * This is a problem when a store location for example 
         * exists in 4 different languages. They would all fall within
         * the selected radius, but we only need one store ID for the 'icl_object_id' 
         * function to get the correct store ID for the current language.         
         */
        if ( $wpsl->i18n->wpml_exists() ) {
            $group_by = 'GROUP BY lat';
        } else {
            $group_by = '';
        }
        /* If autoload is enabled we need to check if there is a limit to the 
         * amount of locations we need to show.
         * 
         * Otherwise include the radius and max results limit in the sql query. 
         */
        if ( isset( $_GET['autoload'] ) && $_GET['autoload'] ) {
            $limit = '';
            if ( $wpsl_settings['autoload_limit'] ) {
                $limit = 'LIMIT %d';
                $placeholder_values[] = $wpsl_settings['autoload_limit'];
            }
            $sql_sort = 'ORDER BY distance '. $limit;
        } else {
            array_push( $placeholder_values, $this->check_store_filter( 'radius' ), $this->check_store_filter( 'max_results' ) );
            $sql_sort = 'HAVING distance < %d ORDER BY distance LIMIT 0, %d';
        }
        $placeholder_values = apply_filters( 'wpsl_sql_placeholder_values', $placeholder_values );
        /* The sql that will check which store locations fall within 
         * the selected radius based on the lat and lng values. 
         */
        $sql = apply_filters( 'wpsl_sql',
               "SELECT post_lat.meta_value AS lat,
                       post_lng.meta_value AS lng,
                       posts.ID, 
                       ( %d * acos( cos( radians( %s ) ) * cos( radians( post_lat.meta_value ) ) * cos( radians( post_lng.meta_value ) - radians( %s ) ) + sin( radians( %s ) ) * sin( radians( post_lat.meta_value ) ) ) ) 
                    AS distance
                  FROM $wpdb->posts AS posts
            INNER JOIN $wpdb->postmeta AS post_lat ON post_lat.post_id = posts.ID AND post_lat.meta_key = 'wpsl_lat'
            INNER JOIN $wpdb->postmeta AS post_lng ON post_lng.post_id = posts.ID AND post_lng.meta_key = 'wpsl_lng'
                $cat_filter 
                 WHERE posts.post_type = 'wpsl_stores' 
                   AND posts.post_status = 'publish' $group_by $sql_sort"
        );
        $stores = $wpdb->get_results( $wpdb->prepare( $sql, $placeholder_values ) );
        if ( $stores  ) {
            $store_data = apply_filters( 'wpsl_store_data', $this->get_store_meta_data( $stores ) );
        }
        return $store_data;
    }

我已经处理过这段代码,之前它只是用下面的代码显示一个分类结果:

$cat_filter = "INNER JOIN $wpdb->term_relationships AS term_rel ON posts.ID = term_rel.object_id
                        INNER JOIN $wpdb->term_taxonomy AS term_tax ON term_rel.term_taxonomy_id = term_tax.term_taxonomy_id
                        AND term_tax.taxonomy = 'wpsl_store_category'
                        AND term_tax.term_id = %d";

所以我猜问题是在$cat_filter元素(只是猜测)。我要做的是两个得到匹配两个下拉结果的a结果。

我已经尝试将OR替换为AND,但是,当然,对我来说没有运气。

有谁能帮我吗?我不要求完整的代码,但你可以有任何建议!

提前感谢!

您首先需要更新您的JavaScript,以便在设置两个分类法术语id时提交它们-它目前仅为"filter"发送单个值。您还需要第二个JOIN到相同的分类法表,这可以通过传入一个数组并将整个内容放入循环来实现。

if ( !empty( $filters ) ){
    // if we have any filters we want to join to term_relationships
    $cat_filter = "INNER JOIN $wpdb->term_relationships AS term_rel
                        ON posts.ID = term_rel.object_id";
    // iterate the tax IDs in the "filter" array, use $i to make each table alias unique
    foreach ( $filters as $i => $filter ){
        // for each filter join to the term_tax table using the tax ID
        $cat_filter.= "INNER JOIN $wpdb->term_taxonomy AS term_tax{$i} 
                            ON term_rel.term_taxonomy_id = term_tax{$i}.term_taxonomy_id
                            AND term_tax{$i}.taxonomy = 'wpsl_store_category'
                            AND term_tax{$i}.term_id = %d";
        // add the tax ID to the values for prepare()
        $placeholder_values[] = $filter;
     }
}