Ask your WordPress questions! Pay money and get answers fast! Comodo Trusted Site Seal
Official PayPal Seal

ACF relationship field on options page - query not working WordPress

  • SOLVED

I have an ACF (advanced custom field) options page. On this options page the user can build info-boxes with a flexible field. The Structure of the boxes:

- make_box (flexible field group)
- - normal_box (flexible field)
- - - location_of_box (relationship field for pages)

There is a field for "hadline" and "content" etc. + the relationship field where all pages and posts are listet and the user can pick some of these. The box should only be visible on the page the user has chosen in this relationship field (see image).

On the "page.php" i have this code:


<?php
// -------------------------------------------------------
// FLEXIBLE content fields for Info Boxes
// -------------------------------------------------------
if( have_rows('info_boxen_anlegen', 'option') ) :

// loop through the rows of data
while ( have_rows('info_boxen_anlegen', 'option') ) : the_row(); ?>

<?php if( get_row_layout() == 'normale_info_box' ): ?>

<?php $posts = get_sub_field('box_loaction');

if( $posts ): ?>
<ul>
<?php foreach( $posts as $post): // variable must be called $post (IMPORTANT) ?>
<?php setup_postdata($post); ?>
<li>
is it working???
</li>
<?php endforeach; ?>
</ul>
<?php wp_reset_postdata(); // IMPORTANT - reset the $post object so the rest of the page works correctly ?>
<?php endif; ?>


<?php endif; endwhile; endif; ?>


and it shows the box that is chosen (in this case the box should appear only on the "kontakt" page, see image). Okay – but the box is chosen on ALL pages, i want it only to be visible on the page "Kontakt". When the user makes a second box and chooses the page e.g. "Jobs", this box is also visible on ALL pages not ony on the page "Jobs". Yeah that is the problem.

So how do i assign the choosen pages to the pages? I have chosen but there seems to be no connection …

Answers (3)

2015-07-12

Andrea P answers:

if I understood correctly your requirements, I don't think that would be feasible.. relationship fields don't actually connect the post with the field, but instead it just give you the chance to retrieve the "connected" post within that very page loop.

I'd suggest to create a custom post type for the box-info, rather than using a repeater with relationship field in an option page.

then you can use a relationship field within the pages, where you select the box that you want to display in that page


herrfischer comments:

For several reasons i don't want to use a post type.


Andrea P comments:

then you could try adding a conditional within the custom field loop, which will display the box only if the post within the relationship field is the same as the currently viewed page's main query.

something like this:


<?php
// -------------------------------------------------------
// FLEXIBLE content fields for Info Boxes
// -------------------------------------------------------

// store the current post id
$current_post_id = get_the_ID();

if( have_rows('info_boxen_anlegen', 'option') ) :

// loop through the rows of data
while ( have_rows('info_boxen_anlegen', 'option') ) : the_row(); ?>

<?php if( get_row_layout() == 'normale_info_box' ): ?>

<?php $posts = get_sub_field('box_loaction');

if( $posts ): ?>

<ul>

<?php foreach( $posts as $post): // variable must be called $post (IMPORTANT) ?>

<?php setup_postdata($post); ?>

<?php if ($post->ID == $current_post_id) { ?>

<li>
is it working???
</li>

<?php } ?>

<?php endforeach; ?>

</ul>

<?php wp_reset_postdata(); // IMPORTANT - reset the $post object so the rest of the page works correctly ?>

<?php endif; ?>

<?php endif; endwhile; endif; ?>


herrfischer comments:

hello andrea, with this code there is nothing shown.


herrfischer comments:

hello andrea, with this code there is nothing shown.


herrfischer comments:

@andrea: If i would have custom post type i would use a query like this:


<?php
// WP_Query arguments
$args = array(
'post_type' => 'infobox',
'meta_query' => array(
'relation' => 'OR',
array(
'value' => '"' . get_the_ID() . '"',
'compare' => 'LIKE'
)
)
);
?>


This would work with post types, but not with option fields. The reason that i don't want to use a post type is that i am not very flexible with these. You can e.g. not chose a template for a custom post type (like with pages), sure i could make a template like "single-cpt_name.php", but i can not make more templates for 1 custom post type. now some could say i have to build more custom post types (i want to serve 30 of these info-boxes with several layouts) but

1: it looks ugly to have 30 post types in the sidebar and - more important for me:
2: i have posts and see only headlines in the overview (i have to open every post to see what is in there and where the box is shown etc.) – in contrast to this, on my options page i see all boxes with all fields on one page which is my final goal

but maybe "options" is just an "options" page like the name says and not for streaming content onto the page … hmmm … but it would be kinda cool. it works perfect, but not with the relationship field, the relation seems to be broken or something.


Andrea P comments:

I think the code was not working because I thought the relationship field was passing an object rather than an id.

try this:

<?php
// -------------------------------------------------------
// FLEXIBLE content fields for Info Boxes
// -------------------------------------------------------


// store the current post id
$current_post_id = get_the_ID();

if( have_rows('info_boxen_anlegen', 'option') ) :

// loop through the rows of data

while ( have_rows('info_boxen_anlegen', 'option') ) : the_row(); ?>

<?php if( get_row_layout() == 'normale_info_box' ): ?>

<?php $posts = get_sub_field('box_loaction');

if( $posts ): ?>

<ul>

<?php foreach( $posts as $post): // variable must be called $post (IMPORTANT) ?>

<?php if ($post == $current_post_id) { ?>

<?php setup_postdata($post); ?>

<li>
is it working???
</li>

<?php } ?>

<?php endforeach; ?>

</ul>

<?php wp_reset_postdata(); // IMPORTANT - reset the $post object so the rest of the page works correctly ?>


<?php endif; ?>
<?php endif; endwhile; endif; ?>


regarding your points, the problem is that a relationship field is not acting into the post that you select within the field, but into the page (in this case the options page), where you placed the field. so if you select the kontakt post in the options page field, the actual kontakt post won't have memory of that selection.

but probably the above code would work for you, because it will check all the info-boxes from the options page, and display only the one which has the current post set into the relationship field (this will also allow for a box to have more than one post connected into the relationship field).


herrfischer comments:

andreas and bobs solutions are both working, i think andrea was faster?


Andrea P comments:

I'm glad it works fine for your needs.

I still have doubts regarding the structure, because in this way you are going to make a quite tricky nested loop every time someone views a posts. your code will retrieve the flexible content fields (all of them) and then loop each of them. for each of them it will then retrieve the relationship field (which could be one or more posts), and loop each of those post ids. it will then print out only data from the box in which the post is the same as the current, but it will browse all the repeater fields and all their relationship posts ids..

though I do understand your points regarding an easier and nicer administration of the boxes. I had a look at it and it is definitely more straight forward than using a post type. but be aware that if you are going to have a lot of these boxes, and a lot of visits, this could have some effects on your site performances. (though you could easily fix them by using caching plugins or similar solutions).


p.s. I just thought that you should move the wp_reset_postdata(); just before the braket that closes the conditional if ($post == $current_post_id) {
in this way it will run the reset_postdata (which is a costly function) only for the box which is actually being displayed, and so only if it actually set up the post data.

p.p.s. regarding the prize, my answer was posted a few hours earlier, so we normally assign the prize to the first correct answer, but in any case it's up to you.

cheers!

2015-07-12

Arnav Joy answers:

Hi ,
Can you show me your site ?


herrfischer comments:

Just uploaded it to my private space:

http://herrfischerhamburg.de/school/kontakt/

As you can see the box with the relationship "Jobs" is shown on both pages jobs and kontakt … i want it to show only on "jobs".

here you can see the boxes:
http://herrfischerhamburg.de/school/wp-admin/admin.php?page=acf-options-info-boxen

and here the fields:
http://herrfischerhamburg.de/school/wp-admin/post.php?post=19&action=edit

user: henning
login: d2alog

2015-07-12

Bob answers:

Please check your site now.
I have modified a code and added comment // Bob wpquestion after it.
Please let me know if it is the output you need?

<?php
// -------------------------------------------------------
// FLEXIBLE content fields for Info Boxes
// -------------------------------------------------------
if( have_rows('info_boxen_anlegen', 'option') ) :
// loop through the rows of data
while ( have_rows('info_boxen_anlegen', 'option') ) : the_row(); ?>
<?php if( get_row_layout() == 'normale_info_box' ): ?>
<?php $posts = get_sub_field('box_loaction');

if( $posts ):
global $post;// Bob wpquestion
if($posts[0] == $post->ID ): // Bob wpquestions
?>
<ul>
<?php foreach( $posts as $post): // variable must be called $post (IMPORTANT) ?>
<?php setup_postdata($post); ?>
<li class="mybox" style="border: 4px solid red;">
<?php // Headline
if (get_sub_field("ib_normal_uberschrift")): ?>
<h2><?php the_sub_field("ib_normal_uberschrift"); ?></h2>
<?php endif; ?>
</li>
<?php endforeach; ?>
</ul>
<?php wp_reset_postdata(); // IMPORTANT - reset the $post object so the rest of the page works correctly ?>
<?php endif; ?>
<?php endif; //Bob wpquestion ?>
<?php endif; endwhile; endif; ?>


herrfischer comments:

hello bob, with this code there is the problem that if i connect a box with two pages (kontakt + jobs) that the box is double on ONE of these pages … .


Bob comments:

Please check now code on your live site I have modified it.






Bob comments:


<?php
// -------------------------------------------------------
// FLEXIBLE content fields for Info Boxes
// -------------------------------------------------------
if( have_rows('info_boxen_anlegen', 'option') ) :
// loop through the rows of data
while ( have_rows('info_boxen_anlegen', 'option') ) : the_row(); ?>
<?php if( get_row_layout() == 'normale_info_box' ): ?>
<?php $posts = get_sub_field('box_loaction');

if( $posts ):

global $post;// Bob wpquestion
if(in_array( $post->ID , $posts ) ): // Bob wpquestions
?>
<ul>
<?php foreach( $posts as $p): // variable must be called $post (IMPORTANT) ?>
<?php if( $p == $post->ID ){ ?>
<?php setup_postdata($p); ?>
<li class="mybox" style="border: 4px solid red;">
<?php // Headline
if (get_sub_field("ib_normal_uberschrift")): ?>
<h2><?php the_sub_field("ib_normal_uberschrift"); ?></h2>
<?php endif; ?>
</li>
<?php } ?>
<?php endforeach; ?>
</ul>
<?php wp_reset_postdata(); // IMPORTANT - reset the $post object so the rest of the page works correctly ?>
<?php endif; //in_array ?>
<?php endif; // posts ?>
<?php endif; // normale_info_box ?>
<?php endwhile;?>
<?php endif; ?>