Support

Account

Home Forums Front-end Issues Count field selection in a WP Query

Solving

Count field selection in a WP Query

  • I’m not sure if it’s possible without having a long lines of code…

    I have a CPT called cars and there is a field called price where the admin puts the price of each car.

    On the front-end, I have a filter that lists price and I am looking for a query that will count how many times it fits under a price bracket.

    For example;

    £5000 (2)
    £10,000 (15)

    This is what I had so far but feel like doing this for each price bracket is stupid and a poor way to do it.

    
    		$args = array( 
    			'post_type'         => 'cars',
    			'posts_per_page'    => -1,
    			'post_status' => 'publish',
    			'meta_query'    => array(
    				'post_type' => 'cars',
    				'post_per_page' => -1,
    				'post_status' => 'publish', 
    				'meta_query' => array(
    					array(
    						'key'       => 'sold',
    						'value'     => array('no'),
    						'compare'   => 'IN',
    					),
    				)
    			)
    		);
    
    		$figure_5000 = new WP_Query( 
    			$args,
    			array( 
    				'key'     => 'price',
    				'value'   => '5000',
    				'type' => 'numeric',
    				'compare' => '<=',
    			) 
    		);
    					
    		$query = new WP_Query( $figure_5000 );
    
    		$figure_5000_total = $query->found_posts;
    
    		echo $figure_5000_total;

    Any ideas, please?

  • I would create a custom taxonomy. The terms in the taxonomy would be the price brackets. Then I would create an acf/save_post filter. In this filter I would get the price entered, figure out what bracket it belongs in and add the correct term to the post. This will allow showing a list of these terms with their counts which is something built into WP. This taxonomy could also be used to easily show a list of items that are in each bracket.

  • Hi @forbiddenchunk

    Absolutely no idea if this would work or not:

    
    <?php
    $args = array( 
    			'post_type'         => 'cars',
    			'posts_per_page'    => -1,
    			'post_status' => 'publish',
    			'meta_query'    => array(
    				'post_type' => 'cars',
    				'post_per_page' => -1,
    				'post_status' => 'publish', 
    				'meta_query' => array(
    					array(
    						'key'       => 'sold',
    						'value'     => array('no'),
    						'compare'   => 'IN',
    					),
    				)
    			)
    		);
    $wp_query = new WP_Query($args);
    if ($wp_query->have_posts()) :
    	$get_price = array();
    	while ($wp_query->have_posts()) : $wp_query->the_post();
    	$get_price[] = get_field('price');
    	endwhile;
    endif; #endif $wp_query
    
    $filter_price = array_unique($get_price);
    
    if($filter_price):
    	foreach($filter_price as $price):
    
    		$figure = new WP_Query( 
    			$args,
    			array( 
    				'key'     => 'price',
    				'value'   => $price,
    				'type' => 'numeric',
    				'compare' => '<=',
    			) 
    		);
    					
    		$query = new WP_Query( $figure );
    
    		$figure_total = $query->found_posts;
    
    		echo $figure_total;
    		
    	endforeach;
    endif; #endif $filter_price

    Basically, you loop all the individual prices and put them into an array
    Filter the prices to remove duplicates
    Then loop the filtered results and pass the value into your query
    Your query then returns the count

    Not tried the code!

  • Hi @jarvis,

    Thanks for replying, I’ve tried it and it only outputs one in a loop;

    2222222222

    I know £10,000 has 1 and £5000 should be around 12

  • Hi @forbiddenchunk

    Try adding some debugging to the code, see what outputs you get at the various stages:

    <?php
    $args = array( 
    			'post_type'         => 'cars',
    			'posts_per_page'    => -1,
    			'post_status' => 'publish',
    			'meta_query'    => array(
    				'post_type' => 'cars',
    				'post_per_page' => -1,
    				'post_status' => 'publish', 
    				'meta_query' => array(
    					array(
    						'key'       => 'sold',
    						'value'     => array('no'),
    						'compare'   => 'IN',
    					),
    				)
    			)
    		);
    $wp_query = new WP_Query($args);
    if ($wp_query->have_posts()) :
    	$get_price = array();
    	while ($wp_query->have_posts()) : $wp_query->the_post();
    	$get_price[] = get_field('price');
    	endwhile;
    endif; #endif $wp_query
    
    echo '<pre>';
    print_r($get_price);
    echo '</pre>';
    
    $filter_price = array_unique($get_price);
    
    echo '<pre>';
    print_r($filter_price);
    echo '</pre>';
    
    if($filter_price):
    	foreach($filter_price as $price):
    		echo '<p>Price: '.$price.'</p>';
    		
    			$args = array(
    				'key'     => 'price',
    				'value'   => $price,
    				'type' => 'numeric',
    				'compare' => '<=',
    			);
    			$wp_query = new WP_Query($args);
    
    		$figure_total = $wp_query->found_posts;
    
    		echo $figure_total;
    		
    	endforeach;
    endif; #endif $filter_price

    So first thing is see what the main array gets
    Then see what the filtered results returns

    When you then loop the filtered array, output the values as a heading

    I did just adjust the query in the foreach, as mentioned, I’ve not tested the code, just trying to cobble it together as a starting point.

  • Hi @jarvis,

    No problem, I appreciate the assistance.

    This is what it came back with;

    Array
    (
    [0] => 5199
    [1] => 6999
    [2] => 7499
    [3] => 7799
    [4] => 9799
    [5] => 10399
    [6] => 8699
    [7] => 6399
    [8] => 7999
    [9] => 7399
    [10] => 4399
    [11] => 4699
    )
    Array
    (
    [0] => 5199
    [1] => 6999
    [2] => 7499
    [3] => 7799
    [4] => 9799
    [5] => 10399
    [6] => 8699
    [7] => 6399
    [8] => 7999
    [9] => 7399
    [10] => 4399
    [11] => 4699
    )
    Price: 5199

    2
    Price: 6999

    2
    Price: 7499

    2
    Price: 7799

    2
    Price: 9799

    2
    Price: 10399

    2
    Price: 8699

    2
    Price: 6399

    2
    Price: 7999

    2
    Price: 7399

    2
    Price: 4399

    2
    Price: 4699

    2

    It’s looping the prices just not the count correctly which is odd.

  • Ah, think we need one minor amend, please try:

    <?php
    $args = array( 
    			'post_type'         => 'cars',
    			'posts_per_page'    => -1,
    			'post_status' => 'publish',
    			'meta_query'    => array(
    				'post_type' => 'cars',
    				'post_per_page' => -1,
    				'post_status' => 'publish', 
    				'meta_query' => array(
    					array(
    						'key'       => 'sold',
    						'value'     => array('no'),
    						'compare'   => 'IN',
    					),
    				)
    			)
    		);
    $wp_query = new WP_Query($args);
    if ($wp_query->have_posts()) :
    	$get_price = array();
    	while ($wp_query->have_posts()) : $wp_query->the_post();
    	$get_price[] = get_field('price');
    	endwhile;
    endif; #endif $wp_query
    
    echo '<pre>';
    print_r($get_price);
    echo '</pre>';
    
    $filter_price = array_unique($get_price);
    
    echo '<pre>';
    print_r($filter_price);
    echo '</pre>';
    
    if($filter_price):
    	foreach($filter_price as $price):
    		echo '<p>Price: '.$price.'</p>';
    		
    			$args = array(
    				'key'     => 'price',
    				'value'   => $price,
    				'type' => 'numeric',
    				'compare' => '<=',
    			);
    			$wp_query = new WP_Query($args);
    
    		$figure_total = $wp_query->found_posts;
    		$count = count( $wp_query->get_posts() );	
    
    		echo '<p>$figure_total: '.$figure_total.' count: '.$count.'</p>';
    		
    	endforeach;
    endif; #endif $filter_price

    I think we need count not found

  • This is what it outputs now @jarvis;

    Array
    (
        [0] => 5199
        [1] => 6999
        [2] => 7499
        [3] => 7799
        [4] => 9799
        [5] => 10399
        [6] => 8699
        [7] => 6399
        [8] => 7999
        [9] => 7399
        [10] => 4399
        [11] => 4699
    )
    Array
    (
        [0] => 5199
        [1] => 6999
        [2] => 7499
        [3] => 7799
        [4] => 9799
        [5] => 10399
        [6] => 8699
        [7] => 6399
        [8] => 7999
        [9] => 7399
        [10] => 4399
        [11] => 4699
    )
    Price: 5199
    
    $figure_total: 2 count: 2
    
    Price: 6999
    
    $figure_total: 2 count: 2
    
    Price: 7499
    
    $figure_total: 2 count: 2
    
    Price: 7799
    
    $figure_total: 2 count: 2
    
    Price: 9799
    
    $figure_total: 2 count: 2
    
    Price: 10399
    
    $figure_total: 2 count: 2
    
    Price: 8699
    
    $figure_total: 2 count: 2
    
    Price: 6399
    
    $figure_total: 2 count: 2
    
    Price: 7999
    
    $figure_total: 2 count: 2
    
    Price: 7399
    
    $figure_total: 2 count: 2
    
    Price: 4399
    
    $figure_total: 2 count: 2
    
    Price: 4699
    
    $figure_total: 2 count: 2

    Is it because it’s not checking against the figure total? e.g. Cars within £5000 = 5, cars within £7000 = 8

  • I think it’s the query in the foreach.

    What if you change it to:

    			$args = array(
    				'posts_per_page'	=> -1,
    				'post_type'		=> 'your post type',
    				'meta_query'	=> array(
    					'relation'		=> 'AND',
    					array(
    						'key'		=> 'price',
    						'value'		=> $price,
    						'compare'	=> '<='
    					),
    				)
    			);

    Specify the post type and see if that works?

    We know the data up to that point is right, so the issue is that query. Just need to tweak it

  • Do any of your price ranges only have 2?
    If you add a wp_reset_query(); after before the closing for each, does that make a difference?

  • Hi @jarvis,

    Apologies for the delay in getting back to you.

    I’ve added the code and this is what was now outputted;

    $figure_total: 0 count: 0

  • Hi @forbiddenchunk,
    Please can you post your code? I’d expect at least one value before seeing no results.
    Looking at the array, do any of the price ranges only have a total of 2?

  • Hi @jarvis,

    No problem, here is the full code;

    $args = array( 
    	'post_type'         => 'cars',
    	'posts_per_page'    => -1,
    	'post_status' => 'publish',
    	'meta_query'    => array(
    		'post_type' => 'cars',
    		'post_per_page' => -1,
    		'post_status' => 'publish', 
    		'meta_query' => array(
    			array(
    				'key'       => 'sold',
    				'value'     => array('no'),
    				'compare'   => 'IN',
    			),
    		)
    	)
    );
    $wp_query = new WP_Query($args);
    if ($wp_query->have_posts()) :
    $get_price = array();
    while ($wp_query->have_posts()) : $wp_query->the_post();
    $get_price[] = get_field('price');
    endwhile;
    endif; #endif $wp_query
    
    echo '<pre>';
    print_r($get_price);
    echo '</pre>';
    
    $filter_price = array_unique($get_price);
    
    echo '<pre>';
    print_r($filter_price);
    echo '</pre>';
    
    if($filter_price):
    foreach($filter_price as $price):
    echo '<p>Price: '.$price.'</p>';
    
    	$args = array(
    		'post_type'         => 'cars',
    		'posts_per_page'	=> -1,
    		'post_type'		=> 'your post type',
    		'meta_query'	=> array(
    			'relation'		=> 'AND',
    			array(
    				'key'		=> 'price',
    				'value'		=> $price,
    				'compare'	=> '<='
    			),
    		)
    	);
    	$wp_query = new WP_Query($args);
    
    $figure_total = $wp_query->found_posts;
    $count = count( $wp_query->get_posts() );	
    
    echo '<p>$figure_total: '.$figure_total.' count: '.$count.'</p>';
    
    endforeach;
    endif; #endif $filter_price
    
    wp_reset_query();

    Thanks again for the help in cracking this!

  • There were 2 errors in the code:
    1) The second loop had post_type twice
    2) The wp_reset_query was in the wrong place

    $args = array( 
    	'post_type'         => 'cars',
    	'posts_per_page'    => -1,
    	'post_status' => 'publish',
    	'meta_query'    => array(
    		'post_type' => 'cars',
    		'post_per_page' => -1,
    		'post_status' => 'publish', 
    		'meta_query' => array(
    			array(
    				'key'       => 'sold',
    				'value'     => array('no'),
    				'compare'   => 'IN',
    			),
    		)
    	)
    );
    $wp_query = new WP_Query($args);
    if ($wp_query->have_posts()) :
    	$get_price = array();
    	while ($wp_query->have_posts()) : $wp_query->the_post();
    		$get_price[] = get_field('price');
    	endwhile;
    endif; #endif $wp_query
    
    echo '<pre>';
    print_r($get_price);
    echo '</pre>';
    
    $filter_price = array_unique($get_price);
    
    echo '<pre>';
    print_r($filter_price);
    echo '</pre>';
    
    if($filter_price):
    foreach($filter_price as $price):
    echo '<p>Price: '.$price.'</p>';
    
    	$args = array(
    		'post_type'         => 'cars',
    		'posts_per_page'	=> -1,
    		'meta_query'	=> array(
    			'relation'		=> 'AND',
    			array(
    				'key'		=> 'price',
    				'value'		=> $price,
    				'compare'	=> '<='
    			),
    		)
    	);
    	$wp_query = new WP_Query($args);
    
    	$figure_total = $wp_query->found_posts;
    	$count = count( $wp_query->get_posts() );	
    
    	echo '<p>$figure_total: '.$figure_total.' count: '.$count.'</p>';
    	wp_reset_query();
    
    endforeach;
    endif; #endif $filter_price

    I’ve tried the above code and it worked for me!

  • Hi @jarvis,

    Thanks, that’s amazing!

    Just wondering now in the foreach loop how I add my select fields – for example;

    <select name="sort_price" id="sort_price">
    	<option value="" selected disabled>Select...</option>
    	<option value="">All</option>
    	<option value="5000">Up to £5000 (<?php echo $count; ?>)</option>
    	<option value="6000">Up to £6000 (<?php echo $count; ?>)</option>
    	<option value="7000">Up to £7000 (<?php echo $count; ?>)</option>
    	<option value="8000">Up to £8000 (<?php echo $count; ?>)</option>
    	<option value="9000">Up to £9000 (<?php echo $count; ?>)</option>
    	<option value="10000">Up to £10,000 (<?php echo $count; ?>)</option>
    </select>
  • What about something like:

    <?php
    
    if($filter_price):
    
    echo '<select name="sort_price" id="sort_price">';
    echo '<option value="" selected disabled>Select...</option>';
    echo '<option value="">All</option>';
    
    foreach($filter_price as $price):
    echo '<p>Price: '.$price.'</p>';
    
    	$args = array(
    		'post_type'         => 'cars',
    		'posts_per_page'	=> -1,
    		'meta_query'	=> array(
    			'relation'		=> 'AND',
    			array(
    				'key'		=> 'price',
    				'value'		=> $price,
    				'compare'	=> '<='
    			),
    		)
    	);
    	$wp_query = new WP_Query($args);
    
    	$figure_total = $wp_query->found_posts;
    	$count = count( $wp_query->get_posts() );	
    
    	#echo '<p>$figure_total: '.$figure_total.' count: '.$count.'</p>';
    	$round_price = round($price, -3);;
    	echo '<option value="'.$round_price.'">Up to £'.$round_price.' ('.$count.')</option>';
    
    	wp_reset_query();
    
    endforeach;
    
    echo '</select>';
    
    endif; #endif $filter_price

    Again, untested code so may error or need some tweaking!

  • Hi @jarvis,

    It worked, but not 100% but looking better thanks 🙂

    This is the code which I updated slightly;

    $args = array( 
    		'post_type'         => 'cars',
    		'posts_per_page'    => -1,
    		'post_status' => 'publish',
    		'meta_query'    => array(
    			'post_type' => 'cars',
    			'post_per_page' => -1,
    			'post_status' => 'publish', 
    			'meta_query' => array(
    				array(
    					'key'       => 'sold',
    					'value'     => array('no'),
    					'compare'   => 'IN',
    				),
    			)
    		)
    	);
    	$wp_query = new WP_Query($args);
    	if ($wp_query->have_posts()) :
    		$get_price = array();
    		while ($wp_query->have_posts()) : $wp_query->the_post();
    			$get_price[] = get_field('price');
    		endwhile;
    	endif; #endif $wp_query
    	
    	$filter_price = array_unique($get_price);
    	
    	if($filter_price):
    
    		echo '<select name="sort_price" id="sort_price">';
    		echo '<option value="" selected disabled>Select...</option>';
    		echo '<option value="">All</option>';
    		
    		foreach($filter_price as $price):
    		
    			$args = array(
    				'post_type'         => 'cars',
    				'post_status' => 'publish',
    				'posts_per_page'	=> -1,
    				'orderby' => 'meta_value_num',
    				'order' => 'DESC',
    				'meta_query'	=> array(
    					'relation'		=> 'AND',
    					array(
    						'key'		=> 'price',
    						'value'		=> $price,
    						'compare'	=> '<='
    					),
    					array(
    						'key'       => 'sold',
    						'value'     => array('no'),
    						'compare'   => 'IN',
    					)
    				)
    			);
    			$wp_query = new WP_Query($args);
    		
    			$figure_total = $wp_query->found_posts;
    			$count = count( $wp_query->get_posts() );	
    		
    			$round_price = round($price, -3);;
    			echo '<option value="'.$round_price.'">Up to £'.$round_price.' ('.$count.')</option>';
    		
    			
    			wp_reset_query();
    		endforeach;
    		
    		echo '</select>';
    		
    		endif; #endif $filter_price

    It outputs the fields but seems to have duplicated them – so the options are;

    <option value="5000">Up to £5000 (4)</option>
    <option value="7000">Up to £7000 (6)</option>
    <option value="7000">Up to £7000 (8)</option>
    <option value="8000">Up to £8000 (9)</option>
    <option value="10000">Up to £10000 (12)</option>
    <option value="10000">Up to £10000 (1)</option>
    <option value="9000">Up to £9000 (11)</option>
    <option value="6000">Up to £6000 (5)</option>
    <option value="8000">Up to £8000 (10)</option>
    <option value="7000">Up to £7000 (7)</option>
    <option value="4000">Up to £4000 (2)</option>
    <option value="5000">Up to £5000 (3)</option>

    As you can see it duplicates them and some of the counts aren’t right as

    Upto £40000 (0) [cars in that price range]
    Upto £50000 (2) [cars in that price range]
    Upto £50000 (3) [cars in that price range]

  • So you know it worked when you output: echo '<p>$figure_total: '.$figure_total.' count: '.$count.'</p>';

    That doesn’t duplicate?

    So my untested code may just need some refining.

    Have a play, perhaps start off by altering the line you know does work, see if you can get it to show both the rounded price and the count, then start adding the other elements

Viewing 18 posts - 1 through 18 (of 18 total)

You must be logged in to reply to this topic.