Skip Navigation

[Resolved] Query posts using post IDs stored in custom fields in a Repeatable Field Group

This thread is resolved. Here is a description of the problem and solution.

Problem: I have a Repeatable Field Group (RFG) that contains a custom field holding a post ID. I would like to use PHP to get all the RFGs associated with the current posts, then loop over and display the posts in this array in the same order as the corresponding RFGs are sorted in wp-admin.

Solution: Initialize an empty array, which will be used to hold a list of post IDs. Use the toolset_get_related_posts API to query for RFGs as child posts of the current post. Use orderby => rfg_order to sort the RFG results using the visual order applied in wp-admin. Loop over the results using foreach, get the value of the post ID custom field using types_render_field or get_post_meta, and push that value onto the empty array. Call the query_posts WordPress API and provide the array of post IDs in the post__in argument. Use orderby => post__in to preserve the sorted order of the post__in array. Example:

$insert_ids = []; // empty array initialization
$child_posts = toolset_get_related_posts( get_the_ID(), 'mdsc-post-ads', array( 'query_by_role' => 'parent', 'return' => 'post_object', 'orderby' => 'rfg_order' ) );
foreach ($child_posts as $child_post) {
  $insert_ids[] = types_render_field( "mdsc-select-ads", array( "id"=> "$child_post->ID", "output" => "raw" )); // push each field value on to the array
}
query_posts( array (
    'post_type' => 'mdsc-ads',
    'posts_per_page' => -1,
    'post__in' => $insert_ids, // query the array of post IDs directly
    'orderby' => 'post__in',
));

Then loop over those results using a standard loop:

while ( have_posts()) : the_post();
// ... the loop 
endwhile; 
wp_reset_query();

Relevant Documentation:
https://toolset.com/documentation/customizing-sites-using-php/post-relationships-api/#toolset_get_related_posts
https://toolset.com/documentation/customizing-sites-using-php/functions/
https://developer.wordpress.org/reference/classes/wp_query/#order-orderby-parameters

This support ticket is created 4 years, 5 months ago. There's a good chance that you are reading advice that it now obsolete.

This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.

Sun Mon Tue Wed Thu Fri Sat
8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 - -
13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 - -

Supporter timezone: America/New_York (GMT-04:00)

This topic contains 7 replies, has 2 voices.

Last updated by lewisR 4 years, 5 months ago.

Assisted by: Christian Cox.

Author
Posts
#1626537

Hello,

I have a repeating group field (code below) that I would like to use in a query to get posts by their ID. How do I add a comma separator so that this will work? Currently the variable $insert_ids produces the result "45 98". I would like the result to be 45,98. I have tried adding "separator" => "," but this does not work. Can you help? Thanks!

<?php
$child_posts = toolset_get_related_posts( get_the_ID(), 'mdsc-add-speakers', array( 'query_by_role' => 'parent', 'return' => 'post_object' ) );
foreach ($child_posts as $child_post);
$insert_ids = types_render_field( "mdsc-speaker", array( "id"=> "$child_post->ID", "output" => "raw" ));

$ids = array( $insert_ids );
query_posts( array (
'post_type' => 'mdsc-speaker',
'posts_per_page' => -1,
'post__in' => $ids,
));
?>

#1628027

Hi, I think you should use the PHP []= operator in your foreach loop to append the value of each field to an array. Initialize an empty array first, then you can use that array directly in your query_posts query:

$insert_ids = []; // empty array initialization
$child_posts = toolset_get_related_posts( get_the_ID(), 'mdsc-add-speakers', array( 'query_by_role' => 'parent', 'return' => 'post_object' ) );
foreach ($child_posts as $child_post);
$insert_ids[]= types_render_field( "mdsc-speaker", array( "id"=> "$child_post->ID", "output" => "raw" )); // push each field value on to the array

query_posts( array (
'post_type' => 'mdsc-speaker',
'posts_per_page' => -1,
'post__in' => $insert_ids, // query the array of post IDs directly
));
#1631123

Thanks for the response!

Unfortunately I don't think it works (or I'm not sure how to implement).

I'm looking for the 'post__in' to have a result like this:

'post__in' => array( 246,267,289 ),

Any ideas?

#1631175

I'm looking for the 'post__in' to have a result like this:
'post__in' => array( 246,267,289 ),

Okay I see a syntax error in the foreach control of your original code that I overlooked, and it was copied into my response. Then I think the shortcut [] = operator should have a space, and I left it out. Here is an update that fixes those two problems:

$insert_ids = []; // empty array initialization
$child_posts = toolset_get_related_posts( get_the_ID(), 'mdsc-add-speakers', array( 'query_by_role' => 'parent', 'return' => 'post_object' ) );
foreach ($child_posts as $child_post) {
  $insert_ids[] = types_render_field( "mdsc-speaker", array( "id"=> "$child_post->ID", "output" => "raw" )); // push each field value on to the array
}
query_posts( array (
'post_type' => 'mdsc-speaker',
'posts_per_page' => -1,
'post__in' => $insert_ids, // query the array of post IDs directly
));

For clarification, these are two ways of formatting an array in PHP:

$format1 = array( 246, 267, 289 );
$format2 = [246, 267, 289];

Either format is fine, and since PHP 5.4 initializing an empty array as [] is fine. Space after the commas and padding the parentheses/brackets is insignificant, too, so the two arrays above hold identical information. The PHP operator $array[] = will push a value into the $array array, regardless of the format used to initialize the array. So now each time the foreach loop iterates, it will push a value into $insert_ids array. Here is a representation of $insert_ids after each iteration of the foreach loop (assuming the types_render_field function is returning the correct values):

After Loop 1: array( 246 );
After Loop 2: array( 246, 267 );
After Loop 3: array( 246, 267, 289 );

Please let me know the results after applying the update. If it's still not working as expected, turn on server logs and let's debug the code using error_log(). If you're not familiar with server logs, I can show you how to activate them temporarily. Sorry if this is more information that you need, I'm not sure of your level of understanding with PHP, debugging, and logs. Assuming you have a standard wp-config.php file, edit it and look for:

define('WP_DEBUG', false);

Change it to:

define('WP_DEBUG', true);

Then add these lines, just after the WP_DEBUG line:

define('WP_DEBUG_LOG', dirname(__FILE__) . '/error_log.txt');
define( 'WP_DEBUG_DISPLAY', false );
@ini_set( 'display_errors', 0 );
define('WP_DISABLE_FATAL_ERROR_HANDLER',true);

Save those changes in wp-config.php on your test server.

Now you can add some error_log statements to the code and see what's going on line by line:

$child_posts = toolset_get_related_posts( get_the_ID(), 'mdsc-add-speakers', array( 'query_by_role' => 'parent', 'return' => 'post_object' ) );
error_log('relationships API query returned these child posts: ' );
error_log(print_r($child_posts, true));
foreach ($child_posts as $child_post) {
error_log('child post ID: ' . $child_post->ID );
error_log('current child post's mdsc-speaker value: ' );
error_log(types_render_field( "mdsc-speaker", array( "id"=> "$child_post->ID", "output" => "raw" )));
  $insert_ids[] = types_render_field( "mdsc-speaker", array( "id"=> "$child_post->ID", "output" => "raw" )); // push each field value on to the array
error_log('insert_ids array after the foreach loop iteration: ' );
error_log(print_r($insert_ids, true));
}
error_log('final insert_ids array to submit to query_posts: ' );
error_log(print_r($insert_ids, true));

Save the change and test it out. After the page is loaded, look for an error_log.txt file in your site's root directory. You can use FTP or if it's localhost use the command-line or file manager GUI to look for this file in the same directory as wp-config.php. With FTP, you may need to click "Refresh" in your FTP browser to see a new file appear. Open that file using any text editor, then copy and paste the contents of that file in your next reply. Once that is done, you can revert the changes you made to wp-config.php and delete the log file.

If you're using a command-line workflow, you can tail the error log file to see the logs in real time. In *nix, change directory to your site's root directory (the directory holding wp-config.php), then run the tail command:

cd /path/to/site
tail error_log.txt
#1631995
Screen Shot 2020-05-20 at 9.08.25 AM.png

Thank you for the quick and fantastic response. This worked great!

There is only one thing that does not work the way I'd like it to: When I use the drag and drop to change the order of the items the order does not change on the front end. I've done this before by using 'orderby'=>'post__in' but it doesn't seem to work here. Below is the code that I'm using now with updated slugs:

<?php 
				$insert_ids = []; // empty array initialization
				$child_posts = toolset_get_related_posts( get_the_ID(), 'mdsc-post-ads', array( 'query_by_role' => 'parent', 'return' => 'post_object' ) );
				foreach ($child_posts as $child_post) {
				  $insert_ids[] = types_render_field( "mdsc-select-ads", array( "id"=> "$child_post->ID", "output" => "raw" )); // push each field value on to the array
				}
				query_posts( array (
					'post_type' => 'mdsc-ads',
					'posts_per_page' => -1,
					'post__in' => $insert_ids, // query the array of post IDs directly
					'orderby' => 'post__in',
				));
			?> 
			
			<?php while (have_posts()) : the_post(); ?>
				<?php if (has_post_thumbnail()) { ?>
					<?php the_post_thumbnail( 'full', array( 'class' => 'post-ad' ) ); ?>
				<?php } else { ?>
				<?php } ?>
			<?php endwhile; wp_reset_query();  ?>

Thanks again!

#1632427

I think the problem is that the $child_posts RFGs aren't sorted correctly in the results from the toolset_get_related_posts API call, so ordering query_posts by post__in just reflects whatever sorting was implemented in $child_posts. So if you sort those RFG results correctly first, then orderby => post__in in query_posts might preserve that order for you. You should be able to sort the RFG query results using orderby=>rfg_order in the array of arguments for the toolset_get_related_posts API query. There is some information about this in the documentation of the post relationships API here: https://toolset.com/documentation/customizing-sites-using-php/post-relationships-api/#toolset_get_related_posts
Applied to your code:

$child_posts = toolset_get_related_posts( get_the_ID(), 'mdsc-post-ads', array( 'query_by_role' => 'parent', 'return' => 'post_object', 'orderby' => 'rfg_order' ) );

Let me know the results of this update.

#1632429

Thank you so much! This is perfect. Great customer service!

#1632433

My issue is resolved now. Thank you!