Support

Account

Home Forums General Issues Post object with conditions performance, elsif or switch or separate blocks

Solving

Post object with conditions performance, elsif or switch or separate blocks

  • Second try to publish here. I’m looking for some community suggestions and help. How would you optimize this post object with conditions?

    My concern is once conditions will grow to 10 and post object is 10-20 it will cause performance issues as it has to render through conditions before printing the custom field value from the post object.

    My idea is either to go for conditions or just create different blocks instead of conditions and more raw code them without conditions.

    What’s your guys thoughts? The maintenance of the code is more or less the same. Conditions would be a little better but also make the code more complex.

    I’ve been testing elseif vs switch so far. While I’ve seen switch perform much better as soon as conditions grow over 4-5 conditions.

    My questions:
    How would you have written this? Can it be optimized more?
    Would you use elseif or switch? If elsif would you add the default in the top as well as if match it will pass value faster for the most common condition? If switch would you do the same?

    Would you go for conditions or just 10 different acf gutenberg blocks instead?

    Core information:
    – The post object is fetched from an options page.
    – The post object will be ranging from 10-20+
    – The post objects are multilingual but doesn’t matter in the code case but worth to mention.
    – Conditions is defined on edit page by a select field.
    – Conditions will grow up to 10 in the long run.
    – The code example here is just one out of several values fetched. And there will be minor conditions within fields as well if empty or if conditions 2 echo this field instead.

    Post object fetch an image with switch:

    <?php
    
    $conditions = get_field( 'conditions_category' );
    
    $post_object = get_field('post_object_categoryone_1','options'); // Set field to grab
    if( !empty ($post_object) );
            $imageArray_BG = get_field('post_hero_img_1', $post_object->ID); // Array returned by Advanced Custom Fields
    		$imageAlt_BG = esc_attr($imageArray_BG['alt']); // Grab, from the array, the 'alt'
    		$imageURL_BG = esc_url($imageArray_BG['url']); // Grab the full size version
    
    $post_object_2 = get_field('post_object_categorytwo_2','options'); // Set field to grab
    if( !empty ($post_object_2) );
            $imageArray_BG_2 = get_field('post_hero_img_1', $post_object_2->ID); // Array returned by Advanced Custom Fields
    		$imageAlt_BG_2 = esc_attr($imageArray_BG_2['alt']); // Grab, from the array, the 'alt'
    		$imageURL_BG_2 = esc_url($imageArray_BG_2['url']); // Grab the full size version
    
    	switch ($conditions){
    		case "value1":
    			echo '<img src="' .$imageURL_BG_2. '" alt="' .$imageAlt_BG_2. '" class="img-example">';
    			break;
    		
    		case "value2":
    			echo "Value 2";
    			break;
    		
    		case "value3":
    			echo "Value 3";
    			break;
    		
    		case "value4":
    			echo "Value 4";
    			break;
    		
    		default:
    			echo '<img src="' .$imageURL_BG. '" alt="' .$imageAlt_BG. '" class="img-example">';
    	}
    
    // always good to see exactly what you are working with
    
    //echo '<span style="font-size: 11px; font-weight: 400; font-family:andale mono">';
    //var_dump($conditions);
    //echo '<br>';
    //var_dump($imageURL_BG);
    //echo '<br>';
    //var_dump($imageURL_BG_2);
    //echo '<br>';
    //echo '</span>';
    
    ?>
    

    Post object fetch an image with elsif:

    <?php
    
    $conditions = get_field( 'conditions_category' );
    
    $post_object = get_field('post_object_categoryone_1','options'); // Set field to grab
    if( !empty ($post_object) );
            $imageArray_BG = get_field('post_hero_img_1', $post_object->ID); // Array returned by Advanced Custom Fields
    		$imageAlt_BG = esc_attr($imageArray_BG['alt']); // Grab, from the array, the 'alt'
    		$imageURL_BG = esc_url($imageArray_BG['url']); // Grab the full size version
    
    $post_object_2 = get_field('post_object_categorytwo_2','options'); // Set field to grab
    if( !empty ($post_object_2) );
            $imageArray_BG_2 = get_field('post_hero_img_1', $post_object_2->ID); // Array returned by Advanced Custom Fields
    		$imageAlt_BG_2 = esc_attr($imageArray_BG_2['alt']); // Grab, from the array, the 'alt'
    		$imageURL_BG_2 = esc_url($imageArray_BG_2['url']); // Grab the full size version
    
    if($conditions == 'value1') {
     	echo '<img src="' .$imageURL_BG_2. '" alt="' .$imageAlt_BG_2. '" class="img-example">';
    }
    elseif($conditions == 'value2') {
     	echo "Value 2";
    }
    elseif($conditions == 'value3') {
            echo "Value 3";
    }
    elseif($conditions == 'value4') {
            echo "Value 4";
    }
    else{
    	echo '<img src="' .$imageURL_BG. '" alt="' .$imageAlt_BG. '" class="img-example">';
    }
    
    // always good to see exactly what you are working with
    //echo '<span style="font-size: 11px; font-weight: 400; font-family:andale mono">';
    //var_dump($conditions);
    //echo '<br>';
    //var_dump($imageURL_BG);
    //echo '<br>';
    //var_dump($imageURL_BG_2);
    //echo '<br>';
    //echo '</span>';
    
    ?>
  • I’m a little confused by your question.

    You said that there would be 20+ post objects.

    Do you mean that you will have 20+ lines of code that looks like this

    
    $post_object = get_field('post_object_categoryone_1','options'); // Set field to grab
    

    or that the above post object field can contain 20 plus posts?

    If you will have 20+ calls to ACF to get 20+ post object fields then this would cause a performance issue due to the number of DB queries that will need to be done. I would look at ways to avoid this. For example a relationship field which allows posts in the relationship to be put in the order that they should be shown so that there is only a single query to get all of the posts.

    However, if you will only have the 2 post object fields that will contain these 20+ posts then this would not be an issue because each field only creates a single query.

    Beyond that it depends on what you are doing once you have all of the posts, there is no indication of what you’ll be doing in each case based on the conditions. Remember that in some cases every call to get_field() and other ACF function may result in additional DB queries depending on if the meta value are cached, and if you get a post object and then use get_field('field-name', $post_object->ID) more than likely the meta values have not been cached. This is one of the reasons for using a loop as shown for a relationship field because calling setup_postdata($post); causes WP to get all the meta values for a post in a single call and cache them. This can be simulated by doing get_post_meta($post_object->ID); which results in the same thing, WP gets all of the meta values for the post in a single query and caches them.

    As far as using if () {} elseif () {} else {} syntax or a switch statement. For me this has nothing to do with performance even if one is more performant than the other. For me it has to do with what the code looks like. Long strings of elseifs are extremely difficult to keep straight an make the code difficult to read and maintain. I will use an, if or an if/else, or sometimes even an if/elseif/else if I’m sure that there will only ever be 1, 2 or 3 possibilities, but beyond that and in cases where I think that the cases can grow in the future will always use a switch statement. When I open someone else’s code and see 20 elsif’s with simple conditions the first thing you will here is me saying “WTF”.

    But that said about elseif’s, there are times when the if conditions are too complex to be dealt with in a switch statement. These or meant for simple conditions.

  • Hi John!

    Reading post object, in the end it will be around 20+ different post objects and 5-10 different categories. Each category will have 5-20 post objects.

    See below if this make sense.

    $post_object = get_field('post_object_categoryONE_1','options')
    $post_object_2 = get_field('post_object_categoryTWO_1','options')

    And this is the code part we are referring to:

    $post_object = get_field('post_object_categoryone_1','options'); // Set field to grab
    if( !empty ($post_object) );
            $imageArray_BG = get_field('post_hero_img_1', $post_object->ID); // Array returned by Advanced Custom Fields
    		$imageAlt_BG = esc_attr($imageArray_BG['alt']); // Grab, from the array, the 'alt'
    		$imageURL_BG = esc_url($imageArray_BG['url']); // Grab the full size version

    One post object contain one post. I see now what you mean, relationship would be smarter code and query once to receive all meta. I didn’t think about each new DB queries here. But in this case I need to fetch one post per post object strictly even if it from the side doesn’t make sense.

    Regarding the conditions it displays a different post object category based on which category the page have selected which is a select field on the page. Like if we would have 20 post objects fruits and 20 post object vegetables. Then the first post object in fruits would show apple while if the category was vegetables it would show carrot as the first post object field.

    But with what you said I should maybe skip conditions here and make 10 different blocks as this would reduce the DB queries, as each block would then represent the conditions. That way I would limit the calls to one extent. Which maybe wouldn’t have been an issue with the relationship field as you explained using one call to fetch all posts in one query.

    But looking at a whole page with other plugins DB calls such as WPML and other together with other page custom fields the amount of fields maybe is much it’s relative I guess, the number must be compared to each function what you try to do to determine if it’s much or not. But logged in I have just as an example SQL (233 queries|62.61 ms). It might still be ways to optimize the DB queries here even if I’m not going with the relationship fields, as one example as you suggested below regarding get_post_meta()

    Is there an easy way to check if the queries is cached or not? I also use redis object cache. But I anyhow wouldn’t prefer to rely on cache it should be beneficial not a must.

    This can be simulated by doing get_post_meta($post_object->ID); which results in the same thing, WP gets all of the meta values for the post in a single query and caches them.

    Could you show me this in one of my examples above, I didn’t make it work. Where would you like to place it?

    Thanks for the answer regarding if/elseif/else and switch conditions.

  • If I needed to use 20+ post object fields in a single page, depending on how often the posts selected would be changed, if this was causing a performance issue, I would find a way to cache the results, for example storing all 20+ results in a single transient that could be loaded using a single db call.

    I honestly don’t know if there is a way to tell if meta values have already been cached. When I’m trying to figure this out I generally install a query monitor plugin and test first with and then without the call to get_post_meta(). If the queries are reduced I leave it in.

    Another thing you might consider is if you’re actually going to use the post data. Will you use the post title, excerpt, content, ect, OR will you only be using custom fields from those posts. If you will not be using standard post field content then you don’t really need the post object and just the ID would be needed to get the custom fields. You can do this by either setting the field to return an array or by get_field('post_object', false, false);

  • I honestly don’t know if there is a way to tell if meta values have already been cached. When I’m trying to figure this out I generally install a query monitor plugin and test first with and then without the call to get_post_meta().

    Using https://wordpress.org/plugins/query-monitor/ does any of them actually say based on real queries cached or not? Using both but right now using https://wordpress.org/plugins/blackbar/

    If the queries are reduced I leave it in.

    What do you mean with leave it in? If queries is reduced it means not cache, or am I misunderstanding you or just getting late here..

    Another thing you might consider is if you’re actually going to use the post data. Will you use the post title, excerpt, content, ect, OR will you only be using custom fields from those posts. If you will not be using standard post field content then you don’t really need the post object and just the ID would be needed to get the custom fields. You can do this by either setting the field to return an array or by get_field('post_object', false, false);

    In this I only use custom fields. Could you give me a full visual example as I don’t think I understand what you mean with “or by get_field('post_object', false, false);

  • If I would for some reasons convert to relationship can I still use get_field without post_object->ID? As I prefer get_field queries to structure the quries before echo them over the_field directly into the echo.

    Just having a quick look at https://www.advancedcustomfields.com/resources/relationship/ where the_field is used once using setup_postdata();. Just did a quick test but even if I setup setup_postdata(); I need to call

    within the foreach loop:

    		$imageArray_BG = get_field('post_hero_img_1', $post_object->ID); // Array returned by Advanced Custom Fields
    		$imageAlt_BG = esc_attr($imageArray_BG['alt']); // Grab, from the array, the 'alt'
    		$imageURL_BG = esc_url($imageArray_BG['url']); // Grab the full size version 

    Which means all posts in the relationship is not passed in one query, correct?

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

You must be logged in to reply to this topic.