Ask your WordPress questions! Pay money and get answers fast! (more info)

Loop through multiple custom fields with increasing number

  • SOLVED

I have a problem with custom fields that I have been trying to figure out for a while, but with no luck.

I have a section on the site I'm building that let's the users publish content form the the front end. The users content is stored in several custom fields attached to the post. So far so good, everything works as expected.

The problem I have is to figure out the best way to fetch this content.

The post that the user is publishing is divided in small chunks, they can for example add an image, a text, or a video.

The custom fields are created like this for every piece of information:

custom_text
custom_text1
custom_text2

custom_image
custom_image1
custom_image2

custom_video
custom_video1
custom_video2


...and so on.

The problem is, I can never be sure what the user decides to add to his post, and the custom fields for every post will look something like this (<strong>see the increasing numbers, but on different fields?</strong>):

custom_image
custom_text1
custom_image2
custom_video3
custom_text4


It has to be saved this way, for the sorting to work. The content needs to be displayed in the order that the user chose when creating the post.

So, what I need is an advanced custom field loop that loops through these custom fields, and display the content accordingly.

Something like:

php start loop
counter = 0

if custom_text (display custom_text)
else if custom_image (display custom_image)
else if custom_video (display custom_video)

counter++;
end loop


I'm thinking that the counter could increase with one every time, and then loop through it all again for number 1, 2 3 etc.

We don't know how many fields will be created, but there will be a maximum of 40 chunks, so the last digit will be 39.

I have experimented a lot, but haven't yet been able to find the solution.

Any suggestions from you gurus out there? :)

Thanks!

// Jens.

<strong>Update:</strong> After getting some advice from John Cotton below, and for a more clear description of what I'm after, this is what I need:

I need to <strong>load all the post meta data in one go</strong> (<em>get_post_custom</em>) and then loop it through with PHP, and display the fields filled in the correct order.

Answers (2)

2014-11-25

John Cotton answers:

This perhaps isn't an answer to your question, rather a suggestion of a different approach.

Use meta data is great for small pieces of extra data - a particularly when it's structured identically on each post.

But I think you'd be better off making each of those "additions" a full post, but with a parent id of the original post.

That way, you can make full use of the api to pull the elements back.

So a text post would be a post, an image would be a attachment and so on.


Jens Filipsson comments:

Thanks John!
Problem is, I'm using a plugin that is constructed this way, I have only modified it for my needs. I guess my solution is a bit more advanced than was intended for the plugin, but it's also the only way I can go at the moment.

Do you think this could significantly decrease my loading times, or is that not a problem with custom fields?

// Jens.


John Cotton comments:

As a rule, if the plugin doesn't do what you want, don't use the plugin.

I think any technique that involves putting counter values in meta key names is going to perform comparatively poorly.

If you are doing up to 40 database queries for each page load (on top of what would normally happen) then yes, it will take a hit.

Far better performance wise to load all the post meta data in one go (get_post_custom) and the loop through in PHP.


Jens Filipsson comments:

To be fair, it did what I want until you gave me your input :)

Anyway, the function you describe is what I'm looking for.


Jens Filipsson comments:

(I'm kidding of course, I really appreciate your feedback!)

2014-11-25

PHPSmashCode answers:

Hi,

May be you can try something like this


$myvals = get_post_meta($post_id);

foreach($myvals as $key=>$val)
{
echo $key . ' : ' . $val[0] . '<br/>';
}


Jens Filipsson comments:

Hi Hari!

After getting some advice from John Cotton above regarding performace, since there are a lot of fields to each post, this is probably more what I'm after:

I need to load all the post meta data in one go (get_post_custom) and then loop it through with PHP, and display the fields filled in the correct order.


Jens Filipsson comments:

Or maybe get_post_meta does the same thing as get_post_custom?


Jens Filipsson comments:

Or maybe get_post_meta does the same thing as get_post_custom?


Jens Filipsson comments:

I also need a bit more control, since I need to contain it in different divs and apply different styling depending on what kind of content is in the field.


PHPSmashCode comments:

Hi Jens,

I hope you have 3 elements group in each sections/steps in user page. if yes you can try this method.

Not sure it will solve the issue, just a thought

$myvals = get_post_meta(get_the_ID());
$i = 1;
foreach($myvals as $key=>$val)
{
$key = trim($key);
if ( '_' == $key{0} )
continue;
if($i%3 == 1)
{
echo '<div class="block">';
}
$class = '';
if (strpos($key,'text') !== false) {
$class = 'class="p-text"';
}else if (strpos($key,'image') !== false) {
$class = 'class="p-image"';
}else if (strpos($key,'video') !== false) {
$class = 'class="p-video"';
}
echo '<p '.$class.'>'.$key . ' : ' . $val[0] . '<p>';

if($i%3 == 0)
{
echo '</div>';
}
$i++;
}

Let me know if you need help or not 3 field group.


Jens Filipsson comments:

Actually, this is the code I'm having at the moment:

// max custom field index
$number = 40;
// the counter
$counter = '';
// the meta keys to check for
$keys = array(
'custom_text',
'custom_image',
'custom_video'
);
// all our custom field values
$custom_fields = get_post_custom( get_the_ID() );

// loop over our counter
while( $counter < $number ){
// loop over each of the keys
foreach( $keys as $key ){
// check if a custom field with key + counter exists
if( isset( $custom_fields[ $key . $counter ] ) ){
// output the field
// values will be in an array, 0 is the first index.
// you can loop over these as well if you have multiple values.
echo $custom_fields[ $key . $counter ][0];
}
}
// increment the counter
$counter++;
}


I figure this might be the most effective solution. I need to make it possible to style it depending on what kind of field it is, and there will be more fields than this later on.

Thanks!

// Jens.


Jens Filipsson comments:

Ok, I solved it like this:

<?php
// max custom field index
$number = 40;
// the counter
$counter = '';
// the meta keys to check for
$keys = array(
'usp-custom-txt_rubrik',
'usp-custom-bild_rubrik',
'usp-custom-video_rubrik',
'usp-custom-txt_txt',
'usp-custom-bild_txt',
'usp-custom-video_txt'
);
// all our custom field values
$custom_fields = get_post_custom( get_the_ID() );

// loop over our counter
while( $counter < $number ){
// loop over each of the keys
foreach( $keys as $key ){
// check if a custom field with key + counter exists
if( isset( $custom_fields[ $key . $counter ] ) ){
// output the field
// values will be in an array, 0 is the first index.
// you can loop over these as well if you have multiple values.
if (in_array(('usp-custom-txt_rubrik' || 'usp-custom-bild_rubrik' || 'usp-custom-video_rubrik'), $keys)) {
echo '<h2>' . $custom_fields[ $key . $counter ][0] . '</h2>';
}
if (in_array(('usp-custom-txt_txt' || 'usp-custom-bild_txt' || 'usp-custom-video_txt'), $keys)) {
echo '<p>' . $custom_fields[ $key . $counter ][0] . '</p>';
}
}
}
// increment the counter
$counter++;
}
?>


Is this a good enough solution, or is there a better way?


PHPSmashCode comments:

Hi Jens,

You're right, it's a good solution. I don't think there would be another better solution for this problem in current custom field structure.

Thanks.