【问题标题】:Get unpurchased items paginated as Custom My account page content in Woocommerce在 Woocommerce 中将未购买的商品分页为自定义我的帐户页面内容
【发布时间】:2018-09-06 19:05:01
【问题描述】:

首先我想说这是我关于 Stack Overflow 的第一个问题,但是多年来我找到了许多有用的解决方案,所以我要感谢所有参与这里的人。

现在,我的第一个问题...

在我的 woocommerce 设置中,每个产品都是数字下载,客户仅限购买一次。出于安全原因,所有下载将在 14 天后过期。

我们有一些客户已经与我们合作长达 5 年,因此,在浏览产品时,我们决定在他们的帐户中提供一个页面,显示他们尚未购买的产品。只是让他们更容易。

现在,我的问题有两个。首先是下面的代码,它显示了他们帐户仪表板中的页面,我无法让 paginav 工作,所以如果你能看到那里可能有什么问题,请告诉我。

但更大的问题是,如何将查询转换为排序函数? 这意味着,如果客户选择他们可以按“尚未购买”进行排序

或者,如果有人知道更简单的方法来完成此操作,请告诉我。

这是我目前用来显示一个页面的代码,该页面显示他们“尚未购买”的产品

// *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 );

【问题讨论】:

    标签: php sql wordpress woocommerce shortcode


    【解决方案1】:

    您可以简化和优化代码,创建唯一的 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 文件中。经过测试并且可以工作。

    启用新的“我的帐户”选项卡式菜单项

    保存此代码后,您需要刷新 Wordpress 重写规则:
    进入 永久链接 选项页面中的 WordPress 设置并重新保存永久链接。


    按页更改产品数量和列数:

    在短代码中,limit 是产品页数,columns 是列数。

     [products limit='9' columns='3' paginate='true' orderby='' ids='$included_ids']
    


    有用的链接:

    【讨论】:

    • 感谢您抽出宝贵的时间。这不适用于我的主题(Kutetheme),它锁定了网站。因此,将尝试使用股票主题离线并根据需要进行调整。
    • @B.Slover 这段代码应该也适合你,因为我使用的钩子和你的代码一样……你需要先删除旧的相关代码,然后添加这个并保存……然后你必须进入您的 Wordpress 设置并在永久链接中单击“保存更改”……然后新选项卡将显示其内容。这是在不同的网站和工作上进行测试的。再次测试,如果有效,请不要忘记to accept the answer,谢谢。
    • @B.Slover 请注意,此代码适用于 Woocommerce 版本 3.2+
    • 谢谢。我确实删除了旧代码。将在本地安装上重试。感谢您的帮助。
    猜你喜欢
    • 2012-09-29
    • 1970-01-01
    • 2019-04-10
    • 1970-01-01
    • 2016-10-28
    • 1970-01-01
    • 1970-01-01
    • 2016-07-29
    相关资源
    最近更新 更多