在 Woocommerce 中获取分页为自定义我的帐户页面内容的未购买项目
Get unpurchased items paginated as Custom My account page content in Woocommerce
首先我想说这是我关于 Stack overflow 的第一个问题,但多年来我找到了许多有用的解决方案,所以我要感谢所有参与这里的人。
现在,我的第一个问题...
在我的 woocommerce 设置中,每个产品都是数字下载,客户只能购买一次。出于安全原因,所有下载都会在 14 天后过期。
我们有一些客户与我们合作长达 5 年,因此,在浏览产品时,我们决定在他们的帐户中提供一个页面,显示他们 还没有 购买的产品然而。只是让他们更容易。
现在,我的问题有两个方面。首先是下面的代码,它在他们的帐户仪表板中显示了页面,我无法让 paginav 工作所以如果你能看到那里可能有什么问题,请告诉我。
但更大的问题是,如何将查询转换为排序函数?
也就是说,如果客户选择他们可以按 "Not yet purchased"
排序
或者,如果有人知道完成此操作的更简单方法,请告诉我。
这是我当前用于显示向他们展示他们拥有的产品的页面的代码 "Not yet purchased"
// *NOT PURCHASED
add_filter ( 'woocommerce_account_menu_items', 'custom_purchased_products_link', 40 );
add_action( 'init', 'custom_add_products_endpoint' );
add_action( 'woocommerce_account_purchased-products_endpoint', 'custom_populate_products_page' );
// here we hook the My Account menu links and add our custom one
function custom_purchased_products_link( $menu_links ){
// we use array_slice() because we want our link to be on the 3rd position
return array_slice( $menu_links, 0, 2, true )
+ array( 'purchased-products' => 'Not Purchased Yet' )
+ array_slice( $menu_links, 2, NULL, true );
}
// here we register our rewrite rule
function custom_add_products_endpoint() {
add_rewrite_endpoint( 'purchased-products', EP_PAGES );
}
// here we populate the new page with the content
function custom_populate_products_page() {
global $wpdb;
// this SQL query allows to get all the products purchased by the current user
// in this example we sort products by date but you can reorder them another way
$purchased_products_ids = $wpdb->get_col( $wpdb->prepare(
"
SELECT itemmeta.meta_value
FROM " . $wpdb->prefix . "woocommerce_order_itemmeta itemmeta
INNER JOIN " . $wpdb->prefix . "woocommerce_order_items items
ON itemmeta.order_item_id = items.order_item_id
INNER JOIN $wpdb->posts orders
ON orders.ID = items.order_id
INNER JOIN $wpdb->postmeta ordermeta
ON orders.ID = ordermeta.post_id
WHERE itemmeta.meta_key = '_product_id'
AND ordermeta.meta_key = '_customer_user'
AND ordermeta.meta_value = %s
ORDER BY orders.post_date DESC
",
get_current_user_id()
) );
// some orders may contain the same product, but we do not need it twice
$purchased_products_ids = array_unique( $purchased_products_ids );
// if the customer purchased something
if( !empty( $purchased_products_ids ) ) :
// it is time for a regular WP_Query
$purchased_products = new WP_Query( array(
'post_type' => 'product',
'paginate' => true,
'posts_per_page' => 50,
'paginate' => true,
'post_status' => 'publish',
'post__not_in' => $purchased_products_ids,
) );
echo '<div class="woocommerce columns-3">';
echo '<h3>Some Products you have not yet purchased (Max display 39)
</h3>';
woocommerce_product_loop_start();
while ( $purchased_products->have_posts() ) : $purchased_products-
>the_post();
wc_get_template_part( 'content', 'product' );
endwhile;
woocommerce_product_loop_end();
woocommerce_reset_loop();
wp_reset_postdata();
else:
echo 'Nothing purchased yet.';
endif;
}
add_action( 'woocommerce_after_shop_loop_item',
'user_logged_in_product_already_bought', 30 );
您可以简化和优化代码进行唯一 SQL 查询以获取当前客户未购买的产品 ID。然后你可以使用 Woocommerce [products]
短代码来获得这个未购买产品的漂亮分页页面。
所以代码会更加轻便和高效,分页 (在 Woocommerce 3.2+ 上):
// Add a new custom menu item to tabbed "My account" menu
add_filter ( 'woocommerce_account_menu_items', 'add_account_new_menu_item', 30, 1 );
function add_account_new_menu_item( $items ){
// Define the new item position in the tabbed menu
$position = 3;
// Define the new item to include in the tabbed menu
$item = array( 'unpurchased-products' => 'Not purchased' );
return array_slice( $items, 0, ($position - 1), true ) + $item + array_slice( $items, ($position - 1), NULL, true );
}
// Enable the new custom menu item tabbed "My account" menu
add_action( 'init', 'add_account_new_menu_item_endpoint' );
function add_account_new_menu_item_endpoint() {
add_rewrite_endpoint( 'unpurchased-products', EP_PAGES );
// ==> Always reflush rewrite rules the first time:
// ==> Go to the Permalinks options page and re-save the permalinks
}
// Add the corresponding content for this new custom menu item
add_action( 'woocommerce_account_unpurchased-products_endpoint', 'custom_populate_products_page' );
function custom_populate_products_page() {
global $wpdb;
//Unique SQL query to get tne non purchased product Ids
$not_purchased_ids = $wpdb->get_col( "SELECT DISTINCT ID
FROM {$wpdb->prefix}posts
WHERE post_type = 'product'
AND post_status = 'publish'
AND ID NOT IN (SELECT DISTINCT woim.meta_value
FROM {$wpdb->prefix}woocommerce_order_itemmeta AS woim
JOIN {$wpdb->prefix}woocommerce_order_items AS woi ON woim.order_item_id = woi.order_item_id
JOIN {$wpdb->prefix}posts AS p ON woi.order_id = p.ID
JOIN {$wpdb->prefix}postmeta AS pm ON p.ID = pm.post_id
WHERE woim.meta_key = '_product_id' AND pm.meta_key = '_customer_user'
AND pm.meta_value != '{get_current_user_id()}')
" );
$included_ids = implode(',', $not_purchased_ids);
echo do_shortcode("[products limit='9' columns='3' paginate='true' orderby='' ids='$included_ids']");
}
// Rename the default option from sorting select field in My account only
add_filter ( 'woocommerce_catalog_orderby', 'custom_catalog_orderby', 30, 1 );
function custom_catalog_orderby( $options ){
if( is_account_page() )
$options['menu_order'] = __( 'Not purchased yet', 'woocommerce' );
return $options;
}
代码进入您的活动子主题(或活动主题)的 function.php 文件。已测试并有效。
Enable the new My account tabbed menu item
Once this code is saved, you will need to flush Wordpress rewrite rules:
Go in WordPress settings in Permalinks options page and re-save the permalinks.
Changing the number of products by page and the number of columns:
In the shortcode limit
is number of products by page and columns
the number of columns.
[products limit='9' columns='3' paginate='true' orderby='' ids='$included_ids']
有用链接:
首先我想说这是我关于 Stack overflow 的第一个问题,但多年来我找到了许多有用的解决方案,所以我要感谢所有参与这里的人。
现在,我的第一个问题...
在我的 woocommerce 设置中,每个产品都是数字下载,客户只能购买一次。出于安全原因,所有下载都会在 14 天后过期。
我们有一些客户与我们合作长达 5 年,因此,在浏览产品时,我们决定在他们的帐户中提供一个页面,显示他们 还没有 购买的产品然而。只是让他们更容易。
现在,我的问题有两个方面。首先是下面的代码,它在他们的帐户仪表板中显示了页面,我无法让 paginav 工作所以如果你能看到那里可能有什么问题,请告诉我。
但更大的问题是,如何将查询转换为排序函数? 也就是说,如果客户选择他们可以按 "Not yet purchased"
排序或者,如果有人知道完成此操作的更简单方法,请告诉我。
这是我当前用于显示向他们展示他们拥有的产品的页面的代码 "Not yet purchased"
// *NOT PURCHASED
add_filter ( 'woocommerce_account_menu_items', 'custom_purchased_products_link', 40 );
add_action( 'init', 'custom_add_products_endpoint' );
add_action( 'woocommerce_account_purchased-products_endpoint', 'custom_populate_products_page' );
// here we hook the My Account menu links and add our custom one
function custom_purchased_products_link( $menu_links ){
// we use array_slice() because we want our link to be on the 3rd position
return array_slice( $menu_links, 0, 2, true )
+ array( 'purchased-products' => 'Not Purchased Yet' )
+ array_slice( $menu_links, 2, NULL, true );
}
// here we register our rewrite rule
function custom_add_products_endpoint() {
add_rewrite_endpoint( 'purchased-products', EP_PAGES );
}
// here we populate the new page with the content
function custom_populate_products_page() {
global $wpdb;
// this SQL query allows to get all the products purchased by the current user
// in this example we sort products by date but you can reorder them another way
$purchased_products_ids = $wpdb->get_col( $wpdb->prepare(
"
SELECT itemmeta.meta_value
FROM " . $wpdb->prefix . "woocommerce_order_itemmeta itemmeta
INNER JOIN " . $wpdb->prefix . "woocommerce_order_items items
ON itemmeta.order_item_id = items.order_item_id
INNER JOIN $wpdb->posts orders
ON orders.ID = items.order_id
INNER JOIN $wpdb->postmeta ordermeta
ON orders.ID = ordermeta.post_id
WHERE itemmeta.meta_key = '_product_id'
AND ordermeta.meta_key = '_customer_user'
AND ordermeta.meta_value = %s
ORDER BY orders.post_date DESC
",
get_current_user_id()
) );
// some orders may contain the same product, but we do not need it twice
$purchased_products_ids = array_unique( $purchased_products_ids );
// if the customer purchased something
if( !empty( $purchased_products_ids ) ) :
// it is time for a regular WP_Query
$purchased_products = new WP_Query( array(
'post_type' => 'product',
'paginate' => true,
'posts_per_page' => 50,
'paginate' => true,
'post_status' => 'publish',
'post__not_in' => $purchased_products_ids,
) );
echo '<div class="woocommerce columns-3">';
echo '<h3>Some Products you have not yet purchased (Max display 39)
</h3>';
woocommerce_product_loop_start();
while ( $purchased_products->have_posts() ) : $purchased_products-
>the_post();
wc_get_template_part( 'content', 'product' );
endwhile;
woocommerce_product_loop_end();
woocommerce_reset_loop();
wp_reset_postdata();
else:
echo 'Nothing purchased yet.';
endif;
}
add_action( 'woocommerce_after_shop_loop_item',
'user_logged_in_product_already_bought', 30 );
您可以简化和优化代码进行唯一 SQL 查询以获取当前客户未购买的产品 ID。然后你可以使用 Woocommerce [products]
短代码来获得这个未购买产品的漂亮分页页面。
所以代码会更加轻便和高效,分页 (在 Woocommerce 3.2+ 上):
// Add a new custom menu item to tabbed "My account" menu
add_filter ( 'woocommerce_account_menu_items', 'add_account_new_menu_item', 30, 1 );
function add_account_new_menu_item( $items ){
// Define the new item position in the tabbed menu
$position = 3;
// Define the new item to include in the tabbed menu
$item = array( 'unpurchased-products' => 'Not purchased' );
return array_slice( $items, 0, ($position - 1), true ) + $item + array_slice( $items, ($position - 1), NULL, true );
}
// Enable the new custom menu item tabbed "My account" menu
add_action( 'init', 'add_account_new_menu_item_endpoint' );
function add_account_new_menu_item_endpoint() {
add_rewrite_endpoint( 'unpurchased-products', EP_PAGES );
// ==> Always reflush rewrite rules the first time:
// ==> Go to the Permalinks options page and re-save the permalinks
}
// Add the corresponding content for this new custom menu item
add_action( 'woocommerce_account_unpurchased-products_endpoint', 'custom_populate_products_page' );
function custom_populate_products_page() {
global $wpdb;
//Unique SQL query to get tne non purchased product Ids
$not_purchased_ids = $wpdb->get_col( "SELECT DISTINCT ID
FROM {$wpdb->prefix}posts
WHERE post_type = 'product'
AND post_status = 'publish'
AND ID NOT IN (SELECT DISTINCT woim.meta_value
FROM {$wpdb->prefix}woocommerce_order_itemmeta AS woim
JOIN {$wpdb->prefix}woocommerce_order_items AS woi ON woim.order_item_id = woi.order_item_id
JOIN {$wpdb->prefix}posts AS p ON woi.order_id = p.ID
JOIN {$wpdb->prefix}postmeta AS pm ON p.ID = pm.post_id
WHERE woim.meta_key = '_product_id' AND pm.meta_key = '_customer_user'
AND pm.meta_value != '{get_current_user_id()}')
" );
$included_ids = implode(',', $not_purchased_ids);
echo do_shortcode("[products limit='9' columns='3' paginate='true' orderby='' ids='$included_ids']");
}
// Rename the default option from sorting select field in My account only
add_filter ( 'woocommerce_catalog_orderby', 'custom_catalog_orderby', 30, 1 );
function custom_catalog_orderby( $options ){
if( is_account_page() )
$options['menu_order'] = __( 'Not purchased yet', 'woocommerce' );
return $options;
}
代码进入您的活动子主题(或活动主题)的 function.php 文件。已测试并有效。
Enable the new My account tabbed menu item
Once this code is saved, you will need to flush Wordpress rewrite rules:
Go in WordPress settings in Permalinks options page and re-save the permalinks.
Changing the number of products by page and the number of columns:
In the shortcode
limit
is number of products by page andcolumns
the number of columns.[products limit='9' columns='3' paginate='true' orderby='' ids='$included_ids']
有用链接: