Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
3.9k views
in Technique[技术] by (71.8m points)

php - Filtering the Woocommerce $order items By Category (Term)

I've been going round in circles with this problem for a few days now and it's starting to drive me a little mad. I know I have all the pieces but I just can't seem to get them to fit together.

I have a printing template for Woocommerce orders that lists the products in the normal way, the order they are stored in the array which in turn is the order they were placed in the basket etc. However, we want them grouped by Category (Term). So this will mean that all items under term_id 17 are listed first, then all term_id 18, etc.

Ideally, this would be an automatic process where the code reads all of the Terms in use, then steps through them one at a time and outputs any products for that Term that are in the basket. But I'm nowhere near that stage yet.

So far I have had partial success with this code:

foreach ($order->get_items() as $item) {

     $product_id = $item['product_id'];

     $meta = $item['item_meta'];
     $meta = array_filter($meta, function ($key) {
     return !in_array($key, Order::getHiddenKeys());
}, ARRAY_FILTER_USE_KEY);

$terms = get_the_terms ( $product_id, 'product_cat' );

foreach ( $terms as $term ) {
    $cat_id = $term->term_id;
    
    if($cat_id === 18) {
        var_dump($item['name']);
    }
}

This will successfully dump the order items that are categorised in term_id 18. However, if I modify the IF statement like this:

if($cat_id === 18) {
    var_dump($item['name']);
} elseif($cat_id === 17) {
    var_dump($item['name']);
}

I would have expected it to output the term_id 18 items, then the term_id 17 ones AFTER them. Unfortunately, it simply shows the array in the default order of 17, then 18, despite the fact the code is laid out in this fashion.

I thought that maybe it was outputting in this way because it's not modifying the original array, simply masking parts of it at different points. So, I have been experimenting with the array_filter function, but I can't seem the get the logic right. I'm pretty embarrassed to post this attempt as I know it's awful, but this is as far as I've gotten experimenting with array_filter:

function test ($var) {
    foreach ( $terms as $term ) {
        $cat_id = $term->term_id;
    
        if($cat_id === 18) {
            print_r($item['name']);
        }
    }
    return $var;
}
    
foreach ($order->get_items() as $item) {

    $product_id = $item['product_id'];

    $meta = $item['item_meta'];
    $meta = array_filter($meta, function ($key) {
    return !in_array($key, Order::getHiddenKeys());
}, ARRAY_FILTER_USE_KEY);
    
$terms = get_the_terms ( $product_id, 'product_cat' );

print_r(array_filter($terms, "test"));

I know it's significantly wrong, but I just can't get my head around it. I'm fine with basic PHP and Wordpress PHP usage normally, but Woocommerce is so much more complicated! I'd really appreciate any help with this please.

Just to recap, I want the products in the order printed / echoed / etc in Category Order (automatically if anyone feels super generous lol). I don't really mind how this is achieved so long as it's safe and secure obviously.

Apologies for the long post and huge thanks in advance.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

It looks to me like you're looping the orders, but you're not looping the categories you want to be ordering them.

I've not run this code, but the pattern should do what you want I think.

// Group items into Categories - If you have a custom order you wish, pre-populate this array, or you can sort after
$categories = [];
foreach ($order->get_items() as $item) {
    $product_id = $item['product_id'];
    $terms = get_the_terms($product_id, 'product_cat');
    $cat_id = $terms[0]->term_id;
    $categories[$cat_id][] = $item;
}

// Loop Categories
foreach($categories as $category => $items){
    echo sprintf("<h1>%s</h1>", $category);
    //Loop Items in Category
    foreach ($items as $item) {
        print_r($item['name']);
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share

2.1m questions

2.1m answers

63 comments

56.5k users

...