Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Retrieving posts from category with ACF content intact #32

Open
mrkylemac opened this issue Sep 18, 2018 · 9 comments
Open

Retrieving posts from category with ACF content intact #32

mrkylemac opened this issue Sep 18, 2018 · 9 comments

Comments

@mrkylemac
Copy link

mrkylemac commented Sep 18, 2018

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!

@SaFrMo
Copy link
Contributor

SaFrMo commented Sep 18, 2018

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!

@mrkylemac
Copy link
Author

mrkylemac commented Sep 19, 2018

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?

@SaFrMo
Copy link
Contributor

SaFrMo commented Sep 19, 2018

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!

@mrkylemac
Copy link
Author

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! 🤔

@SaFrMo
Copy link
Contributor

SaFrMo commented Sep 20, 2018

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
Copy link
Contributor

SaFrMo commented Sep 26, 2018

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

@mrkylemac
Copy link
Author

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!

@SaFrMo
Copy link
Contributor

SaFrMo commented Sep 28, 2018

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!

@mrkylemac
Copy link
Author

mrkylemac commented Sep 29, 2018 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants