Rest-Easy icon indicating copy to clipboard operation
Rest-Easy copied to clipboard

Retrieving posts from category with ACF content intact

Open mrkylemac opened this issue 6 years ago • 9 comments

Hey, I'm reaching out for help more so than submitting an issue here!

I'd like to: • Retrieve all posts from a specific category and include each post's ACF content (not as meta if I can help it).

Basically, I have a bunch of project posts, all with a 'featured' category that I'd like to feature on my FrontPage.

I would normally write something like:

<?php
$args = array(
	'post_type' => 'post',
	'posts_per_page' => -1,
	'cat' => 3
);
$kyles_query = new WP_Query( $args );

if ( $kyles_query->have_posts() ) {
	while ( $kyles_query->have_posts() ) {
		$kyles_query->the_post();
		$fields = get_fields();
	}
	wp_reset_postdata();

} else {
	// no posts found
}

I'm wondering how I could achieve this with a custom Rest Easy filter or any other suggested method? Thanks a million!

mrkylemac avatar Sep 18 '18 09:09 mrkylemac

Hey! There are two parts I see to this question:

  • First, you're looking to add some posts from a specific category to the front page, which you could do like this:
     function serialize_front_page_posts($post_data){

         // ignore if not front page
         if($post_data->ID != get_option('page_on_front')) {
             return $post_data;
         }

         // your $args, with 'cat' changed to 'category' for get_posts
         $args = array(
	    'post_type' => 'post',
	    'posts_per_page' => -1,
	    'category' => 3
          );

         // get posts in category
         $front_page_posts = get_posts($args);

         // save results in top-level property called "frontPagePosts"
         $post_data['frontPagePosts'] = array();

         // attach serialized post data
         foreach($front_page_posts as $front_page_post) {
             $post_data['frontPagePosts'][] = apply_filter('rez_serialize_post', $front_page_post);
         }

         return $post_data;
     }
     add_filter('rez_serialize_post', 'serialize_front_page_posts');

Give that a try in your rest-easy-filters.php file and see if it works - I haven't tested this code specifically but the general idea is there!

  • Second, you're looking to include ACF content in those retrieved posts, which you could do like this (attaches all ACF data as a top-level property called acf on a serialized page/post):
 /*
  * Serialize ACF content with get_field to respect ACF custom formatting
  */
     function serialize_custom_acf_content($post_data){

         // check to make sure we have ACF installed
         if (!function_exists('get_fields')){
             return $post_data;
         }

         // get ACF fields attached to target post
         $acf_fields = get_fields($post_data['ID']);

         // prep to save serialized fields
         $post_data['acf'] = array();

         if( !empty($acf_fields) ){

             // serialize ACF fields
             foreach( $acf_fields as $name => $value ){
                 $post_data['acf'][$name] = $value;
             }

         }

         return $post_data;
     }
     add_filter('rez_serialize_post', 'serialize_custom_acf_content');

We actually just added this second function to the Vuepress boilerplate here, so if you're using a new-ish version you should already be good to go! If not, you can just paste the code above into src/functions/rest-easy-filters.php and it should work fine.

Let me know if there's any problems there and thanks for reaching out!

SaFrMo avatar Sep 18 '18 14:09 SaFrMo

Thanks Sander, I'm getting closer thanks to your help! To get it working, I had to adjust like so:

Custom Filter

function serialize_front_page_posts($post_data){

    // ignore if not front page
    if( !is_front_page() ) {
        return $post_data;
    }

    $args = array(
       'post_type' => 'post',
       'posts_per_page' => -1,
       'category' => 3
     );

    $front_page_posts = get_posts($args);

    $post_data['frontPagePosts'] = array();

    foreach($front_page_posts as $front_page_post) {
        $post_data['frontPagePosts'][] = apply_filters('rez_serialize_post', $front_page_post);
    }

    return $post_data;
}
add_filter('rez_build_loop_data', 'serialize_front_page_posts');

Using add_filter('rez_build_loop_data', ... instead of add_filter('rez_serialize_post', ... Would this be good practice in doing so?

Result: ACF array mrkylemac 2018-09-19 at 1 47 02 pm

I can see my ACF content via [meta] and attachedMedia but am I missing something to think this should live within the acf array?

mrkylemac avatar Sep 19 '18 04:09 mrkylemac

That absolutely works! I personally usually think of the loop as a pure array of serialized post objects, rather than an object with properties, so I'd lean toward putting frontPagePosts in rez_serialize_post instead of rez_build_loop_data. Was the rez_serialize_post filter not working, or was there a different reason for putting the posts in the loop data? Either way, though, it should get the job done!

You're definitely not wrong in thinking that ACF content should live in the acf property - I'm not sure why it wouldn't serialize after pasting the serialize_custom_acf_content function in and adding it to the rez_serialize_post filter. Can you var_dump $acf_fields after this line:

// get ACF fields attached to target post
$acf_fields = get_fields($post_data['ID']);

and see what you get from that? Thanks!

SaFrMo avatar Sep 19 '18 14:09 SaFrMo

Hmm I assumed the same, It wouldn't work when putting frontPagePosts in rez_serialize_post but rez_build_loop_data does.

Just noticed that I'm getting an Uncaught TypeError: _store2.default.state.loop.map is not a function at CacheCrawler.onNewPage.. Does this make sense to you?

Var Dump bool(false) bool(false) bool(false) bool(false)

Although, if I go and assign an ACF to the home/front page then this data will actually show/repeat within the acf: of each of my frontPagePosts...

Thanks for your help Sander, sorry to drag out! 🤔

mrkylemac avatar Sep 20 '18 00:09 mrkylemac

Not a problem at all, happy to help! 😄

  1. The rez_serialize_post issue - Are you able to serialize any data in rez_serialize_post? If so, are you able to serialize data specifically for the front page? You can test those out by pasting these lines into functions/rest-easy-filters.php:

function test_serialization($post_data){
    $post_data['test_generic'] = 'works';
    return $post_data;
}
add_filter('rez_serialize_post', 'test_serialization');

function test_serialization_front_only($post_data){
    $front_id = get_option('page_on_front');
    if($post_data['ID'] == $front_id || $post_data->ID == $front_id){
        $post_data['test_front'] = 'works';
    }

    return $post_data;
}
add_filter('rez_serialize_post', 'test_serialization_front_only');

Any page you load should then have the test_generic field set to works in the result, and the front page should have both test_generic and test_front set to works. If neither or both of those are happening, we've got an issue with serialize_post filters and can go from there!

  1. The cache-crawler issue - That's a bug on our end, adding an issue to the Vuepress repo to fix! It shouldn't affect anything in this situation, though.

  2. The empty ACF fields - Are the values for those fields empty on the posts in question? If not, I'd recommend echoing the ID in serialize_custom_acf_content to make sure it's looking in the correct post:

     function serialize_custom_acf_content($post_data){

         // check to make sure we have ACF installed
         if (!function_exists('get_fields')){
             return $post_data;
         }

    echo $post_data['ID'];
    echo $post_data->ID;

   // etc...

Let me know if any of those shed any more light on the issue!

SaFrMo avatar Sep 20 '18 21:09 SaFrMo

@mrkylemac Any luck with this? Just wanted to check in!

SaFrMo avatar Sep 26 '18 20:09 SaFrMo

Hey Sander!

I'm unable to serialize any data using add_filter('rez_serialize_post', 'serialize_front_page_posts'); Using rez_build_loop_data and rez_build_site_data work though.

If I test the serialization using rez_build_loop_data with the lines of code you provide, I definitely see test_generic but no result with test_front on the homepage.

I'm still quite confused, apologies!

mrkylemac avatar Sep 28 '18 01:09 mrkylemac

Apologies on our end! I'm not quite sure why this isn't working either, but I'll look some more into it at the start of next week - it might be a symptom of a bigger issue so it'll be good to learn more about. Is there any chance you have a public repo for the site you're working on? No problem if not, but it might be useful. Thank you!

SaFrMo avatar Sep 28 '18 18:09 SaFrMo

No worries Sander, I’ve managed to find a temporary fix.

But, next week let me make my repo public just incase this happens to be a bigger issue..

Thanks again!

On Sat, 29 Sep 2018 at 4:55 am, Sander Moolin [email protected] wrote:

Apologies on our end! I'm not quite sure why this isn't working either, but I'll look some more into it at the start of next week - it might be a symptom of a bigger issue so it'll be good to learn more about. Is there any chance you have a public repo for the site you're working on? No problem if not, but it might be useful. Thank you!

— You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub https://github.com/funkhaus/Rest-Easy/issues/32#issuecomment-425533169, or mute the thread https://github.com/notifications/unsubscribe-auth/ADGhGEo4dw-FrXXsDuholkNN0JfA44Ceks5ufnCdgaJpZM4WthXC .

--

• Mr Kyle Mac Brand, Interaction & Web Development +61 (0) 473 431 067

Mitchell House, Lvl 5, Studio #505 358 Lonsdale St, Melbourne, Victoria 3000 Australia

www.mrkylemac.com Instagram http://www.instagram.com/mrkylemac.work, Twitter http://www.twitter.com/mrkylemac, Dribbble http://www.dribbble.com/mrkylemac

mrkylemac avatar Sep 29 '18 00:09 mrkylemac