Site logo

Archived topic

Auto display ACF fields in GP hook by tags?

15 replies · Started by Eric on March 8, 2021

Viewing posts 1–15 of 16

Hi again GeneratePress Team! I hope you guys have all been staying safe and healthy...

I've been trying to solve another PHP puzzle that I've gotten myself into and after several hours I just can't seem to figure it out... I am trying to display specific ACF fields at the bottom of my posts. This is the (noob) PHP code I've created so far and I have this loaded into the GP hook element to display "generate_after_main_content" for my posts. I am then setting the display rules to a specific post tag.

<div>
<p><a href="<?php echo esc_url( get_permalink(123) ); ?>"><?php echo strtoupper (the_field('ACF1', 123)) ?></a> - <?php the_field('ACF2', 123); ?></p>
<p><a href="<?php echo esc_url( get_permalink(124) ); ?>"><?php echo strtoupper (the_field('ACF1', 124)) ?></a> - <?php the_field('ACF2', 124); ?></p>
<p><a href="<?php echo esc_url( get_permalink(125) ); ?>"><?php echo strtoupper (the_field('ACF1', 125)) ?></a> - <?php the_field('ACF2', 125); ?></p>
</div>

The code is actually working in this form above, but the more time I spent looking for specific post IDs and loading them manually, I soon realized that my noob code leaves me open to tons of human error as I manually load the ID values into the hook! So I started looking for a way to retrieve all fields in the GP hook but only if they match these conditions:

1. Post must be listed under a specific post tag (recipes)
2. Post must actually have an ACF field value to load

I was trying to use this code below to display by tag:

function db_change_content_recipes( $content ) {
    if (has_tag( 'recipes' ) ) {
       
    } else {
    
    }
    return $content;
}
add_filter( 'the_content', 'db_change_content_recipes' );

And I was trying to "hide" the fields with no values using this:

add_filter( 'generate_hook_element_display', function( $display, $element_id ) {
    if ( ***POSTID*** === $element_id ) {
        $your_field = get_post_meta( get_the_ID(), '***ACFFIELDNAME***', true );

        if ( ! $your_field ) {
            $display = false;
        }
    }

    return $display;
}, 10, 2 );

I've tried using these all together but I am just creating critical errors on my site. Is it possible to combine these PHP codes somehow? I want it to auto-display the fields after each of my posts tagged under "recipes" so that I don't have to manually load the post IDs by hand into the hook. And if one of the posts DOESN'T have an ACF value to display, it will just get skipped.

What do you guys think? Please let me know what I'm doing wrong... Thanks again GP Team!

Hi there,

I believe you can just apply the condition on this code:

<div>
<p><a href="<?php echo esc_url( get_permalink(123) ); ?>"><?php echo strtoupper (the_field('ACF1', 123)) ?></a> - <?php the_field('ACF2', 123); ?></p>
<p><a href="<?php echo esc_url( get_permalink(124) ); ?>"><?php echo strtoupper (the_field('ACF1', 124)) ?></a> - <?php the_field('ACF2', 124); ?></p>
<p><a href="<?php echo esc_url( get_permalink(125) ); ?>"><?php echo strtoupper (the_field('ACF1', 125)) ?></a> - <?php the_field('ACF2', 125); ?></p>
</div>

Example:

<div>
<?php 
$permalink = get_permalink(123);
$thefield1 = get_field('ACF1', 123);
$thefield2 = get_field('ACF2', 123);

if ( isset($thefield1) || isset($thefield2) ) {
       echo = '<p><a href="'.esc_url( $permalink ).'">'.$thefield1.'</a> - '.$thefield1.'</p>';
} 
?>
</div>

This checks if ACF1 or ACF2 is is set and has value.

I don't think you'll need has_tag() condition if you've placed this on a hook element that has display rule set to a specific tag because that's already your has_tag condition.

Hi Elvin, thank you for your reply!

Unfortunately, this code you gave me is creating a critical error. :(

Also, I think this is still going to be an issue because I have to place the post IDs in manually for each one to appear, right? What I'm trying to do is create a single function that will automatically grab all the posts under that single tag that have field values available, and then display them all vertically in p tags like I have done here by hand:

<div>
<p><a href="<?php echo esc_url( get_permalink(123) ); ?>"><?php echo strtoupper (the_field('ACF1', 123)) ?></a> - <?php the_field('ACF2', 123); ?></p>
<p><a href="<?php echo esc_url( get_permalink(124) ); ?>"><?php echo strtoupper (the_field('ACF1', 124)) ?></a> - <?php the_field('ACF2', 124); ?></p>
<p><a href="<?php echo esc_url( get_permalink(125) ); ?>"><?php echo strtoupper (the_field('ACF1', 125)) ?></a> - <?php the_field('ACF2', 125); ?></p>
</div>

The function needs to filter out posts that don't have the fields available, so that's why I was trying to incorporate an "if then" condition to check each postID before displaying it as part of the list. And yes, this hook would then display on all of the posts under that tag, similar to a related post list.

My code was an example for structuring the condition.

Also, I think this is still going to be an issue because I have to place the post IDs in manually for each one to appear, right?

Not specifying the ID on the functions normally means it'll take the fields associated to the current post.

Example:

<div>
<?php 
$permalink = get_permalink();
$thefield1 = get_field('ACF1');
$thefield2 = get_field('ACF2');

if ( isset($thefield1) || isset($thefield2) ) {
       echo '<p><a href="'.esc_url( $permalink ).'">'.$thefield1.'</a> - '.$thefield1.'</p>';
} 
?>
</div>

If that doesn't work try to use a command to get the id of the current page or post. You can use get_the_ID()
https://developer.wordpress.org/reference/functions/get_the_id/

Example:

<div>
<?php 
$permalink = get_permalink( get_the_ID() );
$thefield1 = get_field('ACF1', get_the_ID() );
$thefield2 = get_field('ACF2', get_the_ID() );

if ( isset($thefield1) || isset($thefield2) ) {
       echo '<p><a href="'.esc_url( $permalink ).'">'.$thefield1.'</a> - '.$thefield1.'</p>';
} 
?>
</div>

Ok yes, I see what you mean... Just to be clear, this function needs to display all OTHER posts under that same tag as well. So if I use get_the_ID() it will work for that specific post but what about all the other posts under that same tag? I wanted to display them all one after the other vertically, as all of the posts will all have those values filled out individually.

I am hoping to display sort of a list of all OTHER posts under that same tag, and not just the single post. For the recipe example, if this is the format to use for each line:

[ACF1] - [ACF2] ***post123***
[ACF1] - [ACF2] ***post124***
[ACF1] - [ACF2] ***post125***

...this is how I was hoping my fields would look like, displaying all the posts under the same tag:

Best Mac And Cheese Recipes - See our top mac and cheese recipes right here.
Chocolate Shake Recipes - We’ve got the best chocolate shake recipes for you.
Protein Muffin Mix Recipes - Try our protein muffin recipes.

These fields are already pre-existing on some of the other posts, so the function needs to pull all of them under that tag that are set, and filter out the ones that do not have fields entered yet.

Sorry for getting back late.

Consider this:

We can display all your ACF values from specific tag using a custom shortcode.

Check this PHP snippet:

add_shortcode( 'acf_listing', 'acf_listing_func' );
function acf_listing_func($atts) {
    $atts = shortcode_atts( array(
			'post_type' => 'post',
			'taxonomy' => 'post_tag',
			'tax_term' => ''
		), $atts, 'acf_listing' );
	$no_whitespaces = preg_replace( '/\s*,\s*/', ',', filter_var( $atts['tax_term'], FILTER_SANITIZE_STRING ) ); 
    $tax_term_array = explode( ',', $no_whitespaces );
	
	$args = array(
		'post_type' => $atts[ 'post_type' ],
		'tax_query' => array(
			array(
				'taxonomy' => $atts[ 'taxonomy' ],
				'field'    => 'slug',
				'terms'    => $tax_term_array,
			),
		),
	);
echo $atts[ 'tax_term' ];
$query = new WP_Query( $args );

    while ($query->have_posts()) {
        $query->the_post();
		
		$permalink = get_permalink( get_the_ID() );
    	$thefield1 = get_field('acf1', get_the_ID() );
    	$thefield2 = get_field('acf2', get_the_ID() );
		
		if(!empty($thefield1) || !empty($thefield2)){ 
			echo '<p><a href="'.esc_url( $permalink ).'">'.$thefield1.'</a> - '.$thefield2.'</p>'; 
		}

    }
    wp_reset_postdata();
}

This snippet allows you to use shortcode [acf_listing tax_term="sample-tag-1"]. It displays the permalink and acf fields acf1 and acf2 looping on all posts with the specified tax_term.

Taxonomy is left to post_tag by default but if you change your mind on tags and you want to use custom taxonomy or default category you can add taxonomy attribute. You can change the post type as well if you need to.

Example [acf_listing tax_term="movies" taxonomy="category" post_type="custom_post"]

You can also use multiple tags.

Example:

[acf_listing tax_term="sample-tag-1,sample-tag-2"]

Wow! Thank you so much... it worked! :) I just want to know how can I remove the tag slug display at the top? It seems like it will first display the tag slug name, and then will display the list below it. Which part of the code do I remove so that the tag slug is not shown and only the list is displayed?

Also, I am trying to embed this shortcode into a div with some additional CSS styling but at the moment it doesn't seem to display correctly. It appears BEFORE the div for some reason, but I have it loaded into the GP element hook like this:

<div class="extraacflist"><p style="font-weight:600;">YOU MIGHT ALSO LIKE:</p>
<p>
	[acf_listing tax_term="recipes"]</p>
</div>

Thank you again! I'm so happy it worked!

Which part of the code do I remove so that the tag slug is not shown and only the list is displayed?

Ah right my bad. Remove this line:

echo $atts[ 'tax_term' ];

I've added that to check if tax_term attribute was working. I forgot to remove it after knowing it works.

Also, I am trying to embed this shortcode into a div with some additional CSS styling but at the moment it doesn’t seem to display correctly. It appears BEFORE the div for some reason, but I have it loaded into the GP element hook like this:

That's strange.

This is the only thing it's supposed to display.
echo '<p><a href="'.esc_url( $permalink ).'">'.$thefield1.'</a> - '.$thefield2.'</p>';

and it's supposed to display where you put it.

Can you remove the extra <p> and </p> before and after the shortcode in your hook element's html?

Also, can you link me to the page in question to observe?

OK so I removed the tag slug... that worked too! Thanks. Just the div issue left...

I removed the p tags like you asked but the div is still displayed directly after the shortcode. I've added the URL in the "private information" field. Just scroll to the bottom of the page to see it.

I'm not sure what I'm supposed to see here.

Here's what I see on my end: https://share.getcloudapp.com/GGu6w1Pl

Which means there's no <div class="extraacflist">...</div> wrapping the shortcode.

You can actually just wrap the whole thing within the shortcode if you want.

Try adding echo '<div class="extraacflist">'; before the $query = new WP_Query( $args ); line and add echo '</div>'; after the wp_reset_postdata(); line so the loop is wrapped within a div.

YES! That did it... I sank so many hours trying to figure this out... thank you Elvin! You are a scholar and a gentleman! WOOHOO!

Nice one. No problem. Glad you got it sorted. :)

Ok so I've been playing around with it across several posts and it's working great so far! One last thing, I can see that the shortcode has a limit of only displaying 10 posts max... which line of code do I edit to remove the 10 post limit? :) I'd like it to just display as many as possible.

You'll have to modify the $atts and $args value. You'll have to add in 'posts_per_page' to the args.

Example edit:

$atts = shortcode_atts( array(
			'post_type' => 'post',
			'posts_per_page' => -1,
			'taxonomy' => 'post_tag',
			'tax_term' => ''
		), $atts, 'acf_listing' );
	$no_whitespaces = preg_replace( '/\s*,\s*/', ',', filter_var( $atts['tax_term'], FILTER_SANITIZE_STRING ) ); 
    $tax_term_array = explode( ',', $no_whitespaces );
	
	$args = array(
		'post_type' => $atts[ 'post_type' ],
		'posts_per_page' => $atts[ 'posts_per_page' ],
		'tax_query' => array(
			array(
				'taxonomy' => $atts[ 'taxonomy' ],
				'field'    => 'slug',
				'terms'    => $tax_term_array,
			),
		),
	);

On this edit, I've added shortcode attribute posts_per_page and linked its value to the $args for the query. It's set to default value of -1 so it shows all posts by default.

But if you changed your mind, you can add attribute to shortcode to limit it.

Example : if you want to limit it to 5 posts only.
[acf_listing tax_term="sample-tag-1,sample-tag-2" post_per_page="5"]

You can actually add in more $args to the query if you want as long as you know the proper parameters.

You can find them all here: https://developer.wordpress.org/reference/classes/wp_query/

We'll try help you out if in case you get stuck with some logic part (or syntax issues) of the code. :)

Fantastic... thanks again, Elvin! I'll do my best to take it from here :)

This archived topic is closed to new replies.