自定义SQL查询以合并两个分类法

时间:2015-10-07 16:25:10

标签: php sql wordpress

我是SQL + PHP的新手,我试图在插件中添加一个函数,除非出现这个问题,否则一切正常。

Link for my page

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

此操作的代码如下

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 元素中(只是一个猜测)。我想要做的是两个得到与下拉结果相匹配的结果。

我已经尝试用AND取代OR,但当然,对我来说没有运气。

任何人都可以帮我这个吗?我不要求完整的代码,但是你可以提出任何建议!

提前致谢!

1 个答案:

答案 0 :(得分:1)

您首先需要更新JavaScript以在设置时提交分类术语ID - 它目前仅为“过滤器”发送单个值。您还需要第二个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;
     }
}