我想仅根据在结算/送货地址中设置的位置列出可以发送给客户的产品。 (我的所有用户都已登录)
我的每个供应商都可能只运送到某些国家/地区,因此我不想向无法发送给他们的用户展示产品。
为了解决这个问题,我在编辑供应商页面中添加了一个额外的字段,用于保存各个国家(通过多选框),它们可以作为单独的术语元发送。
update_term_meta($term_id, 'vendor_data_shipping_countries', $selected_shipping_countries);
等...
所有这些数据都保存得很好,并在我拨打get_term_meta($term->term_id, 'vendor_data_shipping_countries')[0]
时按如下方式输出。
Array
(
[0] => FR
[1] => GB
)
我现在遇到的问题是过滤产品循环查询,只显示可以通过动作' woocommerce_product_query'来发送给用户的产品。
function ac_vendor_show_deliverable_products($query)
{
// magical query filter here...
// if users location matches any of the vendor products ship to countries then output the product to the user
// $query->set(); ... something...
}
add_action('woocommerce_product_query','ac_vendor_show_deliverable_products');
这是我的技能水平让我失望的地方。我对WC很新,不擅长用操作来操纵查询。更好的是只编写完整的SQL但感觉我会把很多其他东西弄得乱七八糟,过滤是最好的方法。
我希望有人的功夫比我强!有人能想出来吗?
希望有人可以提供帮助。
更新:
我已经设法写出了我想要在SQL中发生的事情
SELECT SQL_CALC_FOUND_ROWS wp_posts.* FROM wp_posts
LEFT JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
LEFT JOIN wp_term_taxonomy ON (wp_term_taxonomy.term_taxonomy_id = wp_term_relationships.term_taxonomy_id)
LEFT JOIN wp_termmeta ON (wp_termmeta.term_id = wp_term_taxonomy.term_id)
WHERE wp_termmeta.meta_key = 'vendor_data_shipping_countries'
AND wp_termmeta.meta_value LIKE '%"GB"%'
AND wp_posts.post_type = 'product'
AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')
GROUP BY wp_posts.ID
ORDER BY wp_posts.menu_order ASC, wp_posts.post_title ASC LIMIT 0, 12
这仅列出已将GB添加为可以运送到的国家/地区的产品。
请注意,meta_value存储为序列化数组,因此最简单的匹配方法是执行LIKE,因为值存储为a:2:{i:0;s:2:"FR";i:1;s:2:"GB";}
。
如果有人能弄清楚如何将该SQL放入woocommerce_product_query
钩子,那么这将是惊人的。但我不能为我的生活弄清楚这是怎么可能的......
https://codex.wordpress.org/Class_Reference/WP_Query上的所有内容都只是为wp_postmeta而不是wp_termmeta添加了SQL。
干杯
答案 0 :(得分:2)
我设法通过使用posts_join和posts_where过滤器来实现这一点。
我希望这可以帮助其他人。
/*
* Add the needed term tables
*/
function ac_vendor_sql_join_term_meta($join)
{
global $wp_query, $wpdb;
//only do this is WC product query
if(isset($wp_query->query_vars['wc_query']) && $wp_query->query_vars['wc_query'] == 'product_query')
{
$join .= ' LEFT JOIN '. $wpdb->term_relationships .' tr1 ON (tr1.object_id = '. $wpdb->posts .'.ID)';
$join .= ' LEFT JOIN '. $wpdb->term_taxonomy .' tt1 ON (tt1.term_taxonomy_id = tr1.term_taxonomy_id)';
$join .= ' LEFT JOIN '. $wpdb->termmeta .' tm1 ON (tm1.term_id = tt1.term_id)';
}
return $join;
}
add_filter('posts_join', 'ac_vendor_sql_join_term_meta');
/*
* Add the needed where statements
*/
function ac_vendor_sql_filter_shipping_where($where, $wp_query)
{
//only do this is WC product query
if(isset($wp_query->query_vars['wc_query']) && $wp_query->query_vars['wc_query'] == 'product_query')
{
//get the users billing country code.
if(is_user_logged_in())
{
$billing_country = get_user_meta(get_current_user_id(), 'billing_country', TRUE);
}
else //default to IP location
{
$geo_locate = WC_Geolocation::geolocate_ip($_SERVER['REMOTE_ADDR']);
$billing_country = $geo_locate['country'];
}
$where .= " AND tm1.meta_key = 'vendor_data_shipping_countries'";
$where .= " AND tm1.meta_value LIKE '%\"". $billing_country ."\"%'";
}
return $where;
}
add_filter('posts_where', 'ac_vendor_sql_filter_shipping_where', 10, 2);