0

I try to order result by custom field value when I use this:

// Search product distance
foreach( $productArrayShop as $id ) {
    $pdistance = $product_obj['current_distance']=get_post_meta($id,'current_distance');
    echo ' Distance = '.$pdistance[0].', ';
    $arrayDistance[] = $pdistance[0];
}
//echo '<b> Founded '.count($arrayDistance).' distance</b> ';

// Orderby distance
foreach ($arrayDistance as $d)
{
    $productd = array
    (
        'post_type' => 'product',
        'posts_per_page'=> -1,
        'order' => 'ASC',
        'orderby' => 'meta_value',
        'meta_key' => 'current_distance',
        'fields' => 'ids',
        'meta_query' => array
        (
            array(
                'key' => 'current_distance',
                'value' => $d,
                'type' => 'NUMERIC',
                'compare'=> '<'
            )
        )
    );
    //Get product id
    $product_post = get_posts($productd);
    //echo $product_post[0].', ';
    //echo count($product_post);
    $a[] = $product_post[0];
}
//echo ' Founded '.count($a).' ID';

$resultD = implode(",", $a);
echo ' ID of product '.$resultD.', ';

Result is: Distance = 62.717, Distance = 726.727, ID of product yes,81322,81322 and only first product appear on screen, make sense because same ID... I don't understand why.

the dump of

$a[]:  array(3) { ["map"]=> string(3) "yes" [0]=> int(81322) [1]=> int(81322) }

Why I have two same ID 81322,81322 ?

If I don't use query ordering, my two product appear (not ordered of course) on screen.

When I trace :

foreach ( $productArrayShop as $id ) {
    $pdistance = $product_obj['current_distance']=get_post_meta($id,'current_distance');
    echo ' Distance = '.$pdistance[0].', ';
    $arrayDistance[] = $pdistance[0];
}

I have 2 distance of my 2 products.

The working code is :

$productd = array(
    'post_type' => 'product',
    'posts_per_page'=> -1,
    'order' => 'ASC',
    'orderby' => 'meta_value',
    'meta_key' => 'current_distance',
    'post__in' => $productArrayShop // Here we get all the posts by the IDs with the right order.
);

$product_post = get_posts($productd);
foreach($product_post as $p) {
    $arrp[] = $p->ID;
}
$result = implode(",", $arrp);
echo ' ID of product '.$result.', ';

// View list of product based on road distance of user position
echo do_shortcode('[products ids="' . $result . '" per_page="8" columns="4" pagination="true" orderby="meta_value" order="ASC"]');

Thanks to @Shibi to help me a lot !

0

From what I understand the $productArrayShop is array of all the products ids.

So you first don't need all the distances. what the point to get the distances? You just need all the products IDs and to order them by the meta_value.

BTW this order should be in the first loop instead of re-query for order.

/* So we don't need this. */
/*
foreach ( $productArrayShop as $id )
{
    $pdistance = $product_obj['current_distance']=get_post_meta($id,'current_distance');
    echo ' Distance = '.$pdistance[0].', ';
    $arrayDistance[] = $pdistance[0];
}
*/

/**
* We dont need to loop for each distance we have already array for all the products IDs its all we need.
 */

$productd = array
(
    'post_type' => 'product',
    'posts_per_page'=> -1,
    'order' => 'ASC',
    'orderby' => 'meta_value',
    'meta_key' => 'current_distance',
    'post__in' => $productArrayShop // Here we get all the posts by the IDs with the right order.
);

$product_post = get_posts($productd);

// Then do something with the products...
print_r($product_post);

/**
 * You can loop to get each post object
 */
foreach($product_post as $p) {
    echo $p->ID;
}

Another thing to help you understand why you got the same IDs 81322. Its because you had 2 distances and in your second loop you select posts if they lower than the first one 62 and after this you select posts that lower than the second one 726.

Ofcource you get the same post. because if its match the first condition and it will match the second too. because you select the posts twice. and you order them with ASC (the lower first) so the same post was in index 0.

Woocommerce [products] shortcode custom orderby

First step you need to add filter to your functions.php that check if you pass the custom orderby value to the shortcode and to set the query args to the meta value that you want.

add_filter('woocommerce_shortcode_products_query', 'woo_products_sc_distance_order', 10, 3);
function woo_products_sc_distance_order($args, $atts, $type) {
    if ($atts['orderby'] == "distance") {
        $args['orderby']  = 'meta_value';
        $args['meta_key'] = 'current_distance';
    }
    return $args;
}

And then you call the shortcode with orderby distance

echo do_shortcode('[products ids="' . $result . '" per_page="8" columns="4" pagination="true" orderby="distance" order="ASC"]');

And basic usage:

[products orderby="distance"]
7
  • thanks for this, it's more clear for me ! just on more question, how I can get the ID of product stored in $product_post ? I have tested get_posts but without result, ID's are in and Array[0] [ID] => 83369 ... [ID] => 88087... but I can't access to him – ilanb Jan 21 '18 at 10:54
  • You just need to loop on the $product_post to get each post object see the answer I added there a little example. – Shibi Jan 21 '18 at 11:05
  • Ok... I used foreach loop but tried to acces with get_posts and not ->ID thanks again @Shibi – ilanb Jan 21 '18 at 11:20
  • After test your solution, I get the product ID ordered by th meta value but when I send to the woocommerce shortcode, value not ordered : foreach($product_post as $p) { $arrp[] = $p->ID; } $result = implode(",", $arrp); echo do_shortcode('[products ids="' . $result . '" per_page="8" columns="4" pagination="true"]'); – ilanb Jan 21 '18 at 11:28
  • You can see result here: screencast.com/t/KpADR1ThgWAo – ilanb Jan 21 '18 at 11:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.