Support

Account

Home Forums Feature Requests Add ability to exclude drafts from Relationship field

Solved

Add ability to exclude drafts from Relationship field

    • bootsz

    • July 17, 2013 at 10:52 pm

    I was recently building a site that relied on user-submitted content where a Relationship field was in use, and the client requested that users should only be able to select published posts. I was a bit surprised that ACF doesn’t have an option for this already. In just about every instance where I’m using a Relationship field it seems to make sense to limit selection to published content only.

    I see three potential solutions, each with varying level of benefit/complexity:

    1) Simply exclude drafts by removing ‘draft’ from the post_status array under core/fields/relationship.php, line 134.

    2) Add a field option to “Exclude Drafts”, or “Show Published Only”

    3) Add a field option to allow an admin to select the exact set of post statuses to display in the relationship field (Publish, Draft, Private, etc.).

    I’m happy to write up this patch, just looking to get some feedback on a preferred approach.

  • ACF actually does have this feature (though I didn’t realize it until your question raised my curiosity).

    You can filter relationship query results using the filters ‘acf/fields/relationship/query’, ‘acf/fields/relationship/query/name={{field_name}}’, and ‘acf/fields/relationship/query/key={{field_key}}’ in increasing specificity. So to get only published posts, you would have something like:

    
    add_filter('acf/fields/relationship/query/name=your_relationship_name', 'relationship_options_filter', 10, 3);
    
    function relationship_options_filter($options, $field, $the_post) {
    	
    	$options['post_status'] = array('publish');
    	
    	return $options;
    }
    
    • bootsz

    • July 18, 2013 at 11:17 am

    Nice find! This does appear to work. So my next question is: Would it still be nice to have this as an option in the UI? I suspect that in many (if not most) cases drafts are unwanted. For me the filters are sufficient, just trying to think of the less technically-inclined.

  • thanks wells5609!
    hi bootsz, yes that would be nice to select this in the options, every time we use this field, i always wonder who needs to select drafts 😉

    • v3nt

    • April 21, 2015 at 8:00 pm

    Hey all – i need to do this too but not sure how to implement the above.

    I’ve placed it in my functions.php and changed name=your_relationship_name to name=related_projects (the name of the field?).

    Is there something else i should do?

    • NML

    • April 27, 2016 at 11:17 pm

    I have just tried the above to no avail.

    Was there anything that else that needs doing?

  • @nml @v3nt you don’t need an acf function to get this working, although it might be nice to integrate something into the admin its not needed and is fairly easy to do this in your theme with or without using the filter mentioned above.

    Here’s how to do without using the filter:
    If you wrap the guts of your relationship loop with a conditional using get_post_status() you can exclude or specify at that point. e.g.

    <?php 
    $posts = get_field('relationship_field_name');
    
    if( $posts ): ?>
        <ul>
        <?php foreach( $posts as $post): // variable must be called $post (IMPORTANT) ?>
            <?php setup_postdata($post); ?>
    
            <?php if ( get_post_status() == 'publish' ) :?>
                <li>
                    <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
                    <span>Custom field from $post: <?php the_field('author'); ?></span>
                </li>
            <?php endif;?>
    
        <?php endforeach; ?>
        </ul>
        <?php wp_reset_postdata(); // IMPORTANT - reset the $post object so the rest of the page works correctly ?>
    <?php endif; ?>

    If you don’t setup post data in your loop just use this instead:

    <?php 
        if ( get_post_status($p->ID) == 'publish' ){
            // loop code 
        }
    ?>

    ref: https://codex.wordpress.org/Function_Reference/get_post_status

    • NML

    • May 4, 2016 at 8:53 pm

    @lucidlips while I agree your solution is simple, I think data entered and set a non-published documents / post entry is not made public, it should not be pulled through as such.

    I think the default should be published only. If a developer wants to change this a php template change should be made available for an override.

    Just my 2 pennies..

    Great code example btw!

  • @nml you’re statement is mostly true for posts marked as ‘draft’ or ‘trash’ but the remainder of post status’s private/future/pending etc still have functional usage in a relationship. Im guessing the author avoided having an opinion and instead let developers make the decision.

    On that note, I think the relationship field could be extended to include a whole range of features that I would find useful, this being one of them.

    • misfist

    • March 28, 2017 at 8:04 am

    @lucidlips I might be confused, but I think this question is about filtering the ACF relationship field UI to exclude draft posts (admin), not how to not show draft posts on the front-end.

    Your solution it explains how to exclude posts of a certain status from a loop, which I’m sure is helpful to many. But, it hasn’t nothing to do with ACF, but rather post loops.

    BTW. post_status is a column in the wp_posts table and is returned with the WP_Post object, so you could also use this condition:

    
    <?php 
        if ( 'publish' === $post->post_status ){
            // loop code 
        }
    ?>
    

    ref: https://codex.wordpress.org/The_Loop
    ref: https://codex.wordpress.org/Class_Reference/WP_Post

  • Why does this field show drafts by default? Is there a reason? This should definitely be an option in the UI and not require any hooks.

  • @wells5609 – this solution was working wonderfully until recently. Anyone know how to address this issue currently (V 5.6.1)?

    Has this stopped working for anyone else?

    @gavin310 – I couldn’t agree more!

    • hcj

    • February 14, 2018 at 1:53 am

    Adding vote for adding post status filter to relationship admin interface as described by @gavin310

  • I just found this topic after a client called me saying posts set as Private are showing up on their website. So is the relationship field really just showing all posts, regardless what status they have? This should never happen! A private post means it’s only meant for logged in users and not for anyone else!

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

You must be logged in to reply to this topic.

We use cookies to offer you a better browsing experience, analyze site traffic and personalize content. Read about how we use cookies and how you can control them in our Cookie Policy. If you continue to use this site, you consent to our use of cookies.