按最近的地点订购产品
Order products by nearest locations
我想在搜索表单中输入位置后按最近的位置订购产品。我使用来自 ACF 的 Google 地图为产品分配位置,该字段称为 "address"。我还 Google 为我的表单和 ACF google 地图半径搜索插件放置了自动完成功能。我的表单重定向到带有 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
你知道这个问题吗?
谢谢
我发现了问题。我的 functions.php 中有两个 meta_query 根据两种不同的规则在页面的两个不同位置显示产品。
并且由插件触发的 ORDER BY 位置仅出现在 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
你知道如何纠正吗?
我有这个 meta_query :
$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 );
}
从中依赖于以下 sql 不显示 orderby 位置的查询:
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) <= ‘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 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 à 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' );
显示由插件触发的排序位置的 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) > ‘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
您知道为什么插件无法在第一个 sql 查询中执行 orderby 吗?
我成功了!!由于 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;
}
我想在搜索表单中输入位置后按最近的位置订购产品。我使用来自 ACF 的 Google 地图为产品分配位置,该字段称为 "address"。我还 Google 为我的表单和 ACF google 地图半径搜索插件放置了自动完成功能。我的表单重定向到带有 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
你知道这个问题吗?
谢谢
我发现了问题。我的 functions.php 中有两个 meta_query 根据两种不同的规则在页面的两个不同位置显示产品。
并且由插件触发的 ORDER BY 位置仅出现在 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
你知道如何纠正吗?
我有这个 meta_query :
$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 );
}
从中依赖于以下 sql 不显示 orderby 位置的查询:
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) <= ‘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 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 à 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' );
显示由插件触发的排序位置的 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) > ‘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
您知道为什么插件无法在第一个 sql 查询中执行 orderby 吗?
我成功了!!由于 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;
}