phpwordpressadvanced-custom-fieldsminshortcode

Smarter way to give out lowest value of ACF field


at the moment I use the following function to give out the lowest number of a ACF field. The code is working but not the smartest and most resource conserving way.

add_shortcode( 'LEASINGFAKTOR', 'leaserate_shortcode' );
function leaserate_shortcode () {
$args = array(
        'posts_per_page'=> -1,
        'post_type'     => 'fahrzeuge',
        'meta_key'      => 'leasingfaktor',
    );
    $low_rate_query = new WP_Query( $args ); 
    $rate = array();

    if( $low_rate_query->have_posts() ):
        while( $low_rate_query->have_posts() ) : $low_rate_query->the_post();
            $rate = get_field('leasingfaktor'); 
            if(isset($rate) && !empty($rate)){
                $rates[] = $rate; 
            }
        endwhile;
        $max_rate = max($rates);
        $min_rate = min($rates);

        endif; wp_reset_query();
        return $min_rate;
}

Any ideas on making it cleaner, faster, smarter?


Solution

  • Well, You can use get_posts instead of using WP_Query because you just need the array of post ids that you can use with get_field, and using get_posts you don't need to do a while loop, and wp_reset_query

    Another improvement that you can do is to use, array_map instead of foreach because you're not trying to generate any HTML here or not doing anything complex. you're just trying to get an array of rates so array_map is better in this case and easy to use and the code will be short.

    So your final code using get_posts and array_map will be like this:

    /**
     * Shortcode function
     */
    function leaserate_shortcode() {
        $query_args = array(
            'posts_per_page' => -1,
            'post_type'      => 'fahrzeuge',
            'meta_key'       => 'leasingfaktor', // phpcs:ignore WordPress.DB.SlowDBQuery
            'fields'         => 'ids', // We just need ids for our work.
        );
    
        /**
         * We will use get_posts instead of using WP_Query
         * Because it's easy to use in this case and $no_found_rows
         * is set to false that will give fast performance
         */
        $post_ids = get_posts( $query_args );
    
        // Set default min rate.
        $min_rate = 0;
    
        // Check if we found ids or not.
        if ( ! empty( $post_ids ) ) {
            /**
             * We don't need to do foreach or for loop here
             * We can use an array map and map the post ids array
             * with the values.
             * So we will have an array of rates in the result
             */
            $rates = array_map(
                function( $id ) {
                    // we use using type transform using (int)
                    // assuming returning value will be a number or string number.
                    return (int) get_field( 'leasingfaktor', $id );
                },
                $post_ids
            );
    
            // Filter empty values and get unique values.
            $rates = array_unique( array_filter( $rates ) );
    
            // Check if the final array is not empty.
            if ( ! empty( $rates ) ) {
                $min_rate = min( $rates );
            }
        }
    
        return $min_rate;
    }
    add_shortcode( 'LEASINGFAKTOR', 'leaserate_shortcode' );