【问题标题】:Order products by nearest locations按最近的地点订购产品
【发布时间】:2018-07-02 15:42:16
【问题描述】:

在搜索表单中输入位置后,我想按最近的位置订购产品。我使用 ACF 的 Google 地图为产品分配位置,该字段称为“地址”。我还为我的表单和 ACF 谷歌地图半径搜索插件提供了谷歌位置自动填充功能。我的表单重定向到带有 lat 和 lng 变量的 URL:

/?s=&post_type=product&lat=43.26768079999999&lng=6.640710899999931

插件应该从这个 url 订购产品。 lat 和 lng 在 URL 中很好地传递。不幸的是,它不会改变搜索产品的顺序。

以下是插件的一些关键功能:

// Join for searching metadata
function acf_google_maps_search_join_to_WPQuery($join) {

    global $wpdb;

    $acf_gms = new acf_gms; 
    $table_name = $acf_gms->table_name();

    if ( 
        isset($_GET['lat']) && !empty($_GET['lat']) 
        && isset( $_GET['lng']) && !empty($_GET['lng']) 
         ) {

        $join .= " LEFT JOIN {$table_name} AS acf_gms_geo ON {$wpdb->posts}.ID = acf_gms_geo.post_id ";

    }

    return $join;

}
add_filter('posts_join', 'acf_google_maps_search_join_to_WPQuery');



// ORDER BY DISTANCE
function acf_google_maps_search_orderby_WPQuery($orderby) {


     if ( 
        isset($_GET['lat']) && !empty($_GET['lat']) 
        && isset( $_GET['lng']) && !empty($_GET['lng']) 
         ) {

        $lat = sanitize_text_field( $_GET['lat'] );
        $lng = sanitize_text_field( $_GET['lng'] );

        $orderby = " (POW((acf_gms_geo.lng-{$lng}),2) + POW((acf_gms_geo.lat-{$lat}),2)) ASC";

    }

    return $orderby;

}
add_filter('posts_orderby', 'acf_google_maps_search_orderby_WPQuery');

这里是传递给结果页面的 sql 查询:

SELECT wp_posts.* 
FROM wp_posts 
INNER JOIN wp_postmeta 
    ON ( wp_posts.ID = wp_postmeta.post_id ) 
INNER JOIN wp_postmeta AS mt1 
    ON ( wp_posts.ID = mt1.post_id ) 
INNER JOIN wp_postmeta AS mt2 
    ON ( wp_posts.ID = mt2.post_id ) 
LEFT JOIN wp_acf_google_map_search_geodata AS acf_gms_geo 
    ON wp_posts.ID = acf_gms_geo.post_id 
WHERE 1=1 
    AND (   
            ( wp_postmeta.meta_key = ‘flash_sale_start’ 
                AND CAST(wp_postmeta.meta_value AS DATE) > ‘20180122’ 
            )
            AND ( mt1.meta_key = ‘flash_sale_end’ 
                AND CAST(mt1.meta_value AS DATE) > ‘20180122’ 
            )
            AND ( mt2.meta_key = ‘flash_sale_start’ 
                AND CAST(mt2.meta_value AS DATE) <= ‘20180127’ 
            )
        ) 
    AND wp_posts.post_type = ‘product’ 
    AND ((wp_posts.post_status = ‘publish’)) 
GROUP BY wp_posts.ID 
ORDER BY (POW((acf_gms_geo.lng-6.640710899999931),2) + POW((acf_gms_geo.lat-43.26768079999999),2)) ASC

你知道这个问题吗?

谢谢

【问题讨论】:

    标签: php sql wordpress woocommerce advanced-custom-fields


    【解决方案1】:

    我发现了问题。我的functions.php中有两个meta_query,用于根据两个不同的规则在页面的两个不同位置显示产品。

    并且插件触发的ORDER BY位置只出现在其中一个sql查询中,而没有出现在这个sql查询中(虽然出现了LEFT JOIN部分):

        SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts 
    INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) 
    INNER JOIN wp_postmeta AS mt1 ON ( wp_posts.ID = mt1.post_id ) 
    INNER JOIN wp_postmeta AS mt2 ON ( wp_posts.ID = mt2.post_id ) 
    

    //下面可以看到插件的le left join部分出现了

    LEFT JOIN wp_acf_google_map_search_geodata AS acf_gms_geo ON wp_posts.ID = acf_gms_geo.post_id WHERE 1=1 AND wp_posts.ID NOT IN (968) AND (
        wp_posts.ID NOT IN (
        SELECT object_id
        FROM wp_term_relationships
        WHERE term_taxonomy_id IN (10)
        )
        ) AND (
        wp_postmeta.meta_key = ‘total_sales’
        AND
        (
        (
        ( mt1.meta_key = ‘flash_sale_start’ AND CAST(mt1.meta_value AS DATE) <= ‘20180125’ )
        AND
        ( mt2.meta_key = ‘flash_sale_end’ AND CAST(mt2.meta_value AS DATE) >= ‘20180125’ )
        )
        )
        ) AND wp_posts.post_type = ‘product’ AND (wp_posts.post_status = ‘publish’ OR wp_posts.post_status = ‘complete’ OR wp_posts.post_status = ‘paid’ OR wp_posts.post_status = ‘confirmed’ OR wp_posts.post_status = ‘unpaid’ OR wp_posts.post_status = ‘pending-confirmation’ OR wp_posts.post_status = ‘cancelled’ OR wp_posts.post_status = ‘private’) 
    GROUP BY wp_posts.ID 
    

    //但是下面的order by部分插件没有出现

    ORDER BY wp_postmeta.meta_value+0 DESC, wp_posts.post_date DESC LIMIT 0, 100
    

    你知道如何解决这个问题吗?

    【讨论】:

      【解决方案2】:

      我有这个元查询:

      $today = current_time('Ymd');
       $args = array (
          'numberposts' => -1,
          'post_status'       => 'publish',
          'post_type'         => 'product',
          'meta_query' => array(
          'relation' => 'AND',
          'start_clause' => array(
              'key'=>'flash_sale_start',
              'value' => $today,
              'compare'=> '<=',
           'type' => 'DATE'
          ),
               'end_clause' => array(
               'key' => 'flash_sale_end',
           'value' => $today,
               'compare' => '>=',
           'type' => 'DATE'
      )
      
             )
      );
      return $args;
      }
      
      // The main shop and archives meta query
      add_filter( 'woocommerce_product_query_meta_query', 'custom_product_query_meta_query', 10, 2 );
      function custom_product_query_meta_query( $meta_query, $query ) {
          if( ! is_admin() ) 
              return custom_meta_query( $meta_query );
      }
      

      其中取决于以下不显示 orderby 位置的 sql 查询:

      SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts 
      INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) 
      INNER JOIN wp_postmeta AS mt1 ON ( wp_posts.ID = mt1.post_id ) 
      INNER JOIN wp_postmeta AS mt2 ON ( wp_posts.ID = mt2.post_id )
      LEFT JOIN wp_acf_google_map_search_geodata AS acf_gms_geo ON wp_posts.ID = acf_gms_geo.post_id WHERE 1=1 AND wp_posts.ID NOT IN (968) AND (
          wp_posts.ID NOT IN (
          SELECT object_id
          FROM wp_term_relationships
          WHERE term_taxonomy_id IN (10)
          )
          ) AND (
          wp_postmeta.meta_key = ‘total_sales’
          AND
          (
          (
          ( mt1.meta_key = ‘flash_sale_start’ AND CAST(mt1.meta_value AS DATE) &lt;= ‘20180125’ )
          AND
          ( mt2.meta_key = ‘flash_sale_end’ AND CAST(mt2.meta_value AS DATE) &gt;= ‘20180125’ )
          )
          )
          ) AND wp_posts.post_type = ‘product’ AND (wp_posts.post_status = ‘publish’ OR wp_posts.post_status = ‘complete’ OR wp_posts.post_status = ‘paid’ OR wp_posts.post_status = ‘confirmed’ OR wp_posts.post_status = ‘unpaid’ OR wp_posts.post_status = ‘pending-confirmation’ OR wp_posts.post_status = ‘cancelled’ OR wp_posts.post_status = ‘private’) 
      GROUP BY wp_posts.ID 
      ORDER BY wp_postmeta.meta_value+0 DESC, wp_posts.post_date DESC LIMIT 0, 100
      

      我也有这个元查询:

      $products = new WP_Query( array (
                  'post_type'         => 'product',
                  'post_status'       => 'publish',
                  'posts_per_page'    => $atts['limit'],
                  'meta_query'        => array(
                      'relation'      => 'AND',
                      'start_clause'  => array(
                          'key'       =>'flash_sale_start',
                          'value'     => $today,
                          'compare'   => '>',
                          'type'      => 'DATE'
                      ),
                      'end_clause'    => array(
                          'key'       => 'flash_sale_end',
                          'value'     => $today,
                          'compare'   => '>',
                          'type'      => 'DATE'
                      ),
              'limit_clause'    => array(
                          'key'       => 'flash_sale_start',
                          'value'     => $limitdate,
                          'compare'   => '<=',
                          'type'      => 'DATE'
                      )
      )
      
              ));
      }
      
              ob_start();
      
              if ( $products->have_posts() ) { ?>
      
                  <?php woocommerce_product_loop_start(); ?>
      
                      <?php while ( $products->have_posts() ) : $products->the_post(); ?>
      
                          <?php wc_get_template_part( 'content', 'product' ); ?>
      
                      <?php endwhile; // end of the loop. ?>
      
                  <?php woocommerce_product_loop_end(); ?>
      
                  <?php
              } else {
                  do_action( "woocommerce_shortcode_products_loop_no_results", $atts );
                  echo "<p>Aucune vente &#224; venir pour le moment.</p>";
              }
      
              woocommerce_reset_loop();
              wp_reset_postdata();
      
              return '<div class="woocommerce columns-' . $atts['columns'] . '">' . ob_get_clean() . '</div>';
          }
      
          add_shortcode( 'upcoming_sales', 'upcoming_sales' );
      

      其中依赖于显示插件触发的 orderby 位置的 sql_query:

      SELECT wp_posts.* 
      FROM wp_posts 
      INNER JOIN wp_postmeta 
          ON ( wp_posts.ID = wp_postmeta.post_id ) 
      INNER JOIN wp_postmeta AS mt1 
          ON ( wp_posts.ID = mt1.post_id ) 
      INNER JOIN wp_postmeta AS mt2 
          ON ( wp_posts.ID = mt2.post_id ) 
      LEFT JOIN wp_acf_google_map_search_geodata AS acf_gms_geo 
          ON wp_posts.ID = acf_gms_geo.post_id 
      WHERE 1=1 
          AND (   
                  ( wp_postmeta.meta_key = ‘flash_sale_start’ 
                      AND CAST(wp_postmeta.meta_value AS DATE) &gt; ‘20180122’ 
                  )
                  AND ( mt1.meta_key = ‘flash_sale_end’ 
                      AND CAST(mt1.meta_value AS DATE) &gt; ‘20180122’ 
                  )
                  AND ( mt2.meta_key = ‘flash_sale_start’ 
                      AND CAST(mt2.meta_value AS DATE) &lt;= ‘20180127’ 
                  )
              ) 
          AND wp_posts.post_type = ‘product’ 
          AND ((wp_posts.post_status = ‘publish’)) 
      GROUP BY wp_posts.ID 
      ORDER BY (POW((acf_gms_geo.lng-6.640710899999931),2) + POW((acf_gms_geo.lat-43.26768079999999),2)) ASC
      

      你知道为什么插件不能在第一个sql查询中做orderby吗?

      【讨论】:

        【解决方案3】:

        我设法使它工作!由于 woocommerce 有自己的东西来订购产品,所以只需要编写一个这样的函数:

        if(isset($_GET['lat']) and $_GET['lat'] != "" and isset($_GET['lng']) and $_GET['lng'] != "")
            {
            add_filter( 'woocommerce_default_catalog_orderby', 'custom_woocommerce_get_catalog_ordering_args' 
        
            );
            }
            function custom_woocommerce_get_catalog_ordering_args( $args ) {
        
            $lat = sanitize_text_field( $_GET['lat'] );
            $lng = sanitize_text_field( $_GET['lng'] );
        
                    $args['orderby'] = ' (POW((acf_gms_geo.lng-{$lng}),2) + POW((acf_gms_geo.lat-
        
            {$lat}),2))';
                    $args['order'] = 'ASC';
                    $args['meta_key'] = '';
        
                return $args;
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-08-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-05-08
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多