0

I have two Custom post types: question and answer. "Questions" are hierarchical and they are parent posts for answers - which are child posts. For every answer, there's a parent question. When someone asks a question, every answer given is correctly attributed to the same question. This has already been nicely done in the website. While I am building the APP, I can pull in all questions, but when it comes to answers, I can't seem to filter out answer by parent question.

All questions can be obtained like this: https://domain.com/wp-json/wp/v2/questions

For answers, I am using custom endpoint with this code:

add_action( 'rest_api_init', 'custom_api_get_all_posts' );      
function custom_api_get_all_posts() {
    register_rest_route( 'app/v1', '/answers', array(
        'methods' => 'GET',
        'callback' => 'custom_api_get_all_posts_callback'
    ));
}

function custom_api_get_all_posts_callback( $request ) {

    // Initialize the array that will receive the posts' data.    

    $posts_data = array();
    // Receive and set the page parameter from the $request for pagination purposes
    $paged = $request->get_param( 'page' );
    $paged = ( isset( $paged ) || ! ( empty( $paged ) ) ) ? $paged : 1; 
    // Get the posts using the 'post' and 'news' post types
    // $avatar_url = get_avatar_url ( get_the_author_meta('ID'), $size = '50' ); 
    $posts = get_posts( array(
        'paged' => $paged,                     
        'posts_per_page' => 10,   
        'post_type' => 'answer', 
    )); 
    if ( is_array( $filter ) && array_key_exists( 'question', $filter ) ) {
        $args['post_parent_id'] = $filter['question'];
    }

    // Loop through the posts and push the desired data to the array we've initialized earlier in the form of an object
    foreach( $posts as $post ) {
        $id = $post->ID; 
        $posts_data[] = (object) array( 
            'id' => $id, 
            'slug' => $post->post_name, 
            'type' => $post->post_type,
            'title' => $post->post_title,
            'content' => $post->post_content,
            'question' => $post->post_parent,
        );
    }                
    return $posts_data;                   
}

And by this, I can get all answers with their IDs, Answer Title, Content, and Parent Question Id in GET response at https://domain.com/wp-json/app/v1/answers

QUESTION: How do I have to modify the code to be able to filter out specific answers based on question ID, something like: https://domain.com/wp-json/app/v1/answers?question=1234 where 1234 is an ID for a parent question whose answers we need to display. All suggested filter plugins have failed to work, I've tried different forms of codes for so many hours, I really appreciate your help :)

Thanks! (Both question and answer are CPTs, and I am using WP Version - 4.9.8)

0

I'd start out by checking that your request is being passed properly. I'd do that by changing this:

function custom_api_get_all_posts_callback( $request ) {

  // Initialize the array that will receive the posts' data.    

  $posts_data = array();

to this:

function custom_api_get_all_posts_callback( $request ) {

  // Initialize the array that will receive the posts' data.    

  echo "<pre>";
  print_r( $request );
  echo "</pre>";

  $posts_data = array();

... and then calling the page as you do: https://domain.com/wp-json/app/v1/answers?question=1234

Then you should be able to see your request.


It looks like that your code is returning a list of posts. But if you then add a check in the top saying (if id is specified, then return just a single post). It would look something like this:

if( $request->get_param( 'id' ) ):
  // Find that page and return just that.
endif;
  • Thanks @Zeth for your input, trying this out now, will let you know shortly if it works. Thanks! – Wakadala Mato Philip Nov 5 '18 at 6:06
  • Thanks again for your time @Zeth, I appreciate your help. How should I find the page and display it between the if statement, any ideas on which code to use? Also, do I have to modify the endpoint URL to match the format: answers?question=ID? NB: I am not looking to return a single post, but posts that share a parent_post_ID, represented by the field: parent. Thanks a bunch! – Wakadala Mato Philip Nov 5 '18 at 6:42
  • Hi again. If you add 'post_parent' to the get_posts-statement from your own code, then it will only return children to the post. And I'd use the same approach as the code you've writting for it. Let me know if it makes sense or if I need to elaborate. – Zeth Nov 5 '18 at 6:49
  • I haven't figured it out yet, still working up scenarios. – Wakadala Mato Philip Nov 6 '18 at 6:52
  • @WakadalaMatoPhilip - Please post the solution, so others (who find this) can find the solution on this page. – Zeth Nov 9 '18 at 2:35
0

The Question was about filtering out child posts by parent posts, both of which are custom post types in wordpress. This is how I did it, works great.

You can add this code in your own simple plugin: (Just create a new folder under plugins, add this code to index.php, ensure to enclose the code between <?php //code here, with a proper plugin header; ?> and activate the plugin.

add_action( 'rest_api_init', 'custom_api_get_all_posts' );      
   function custom_api_get_all_posts() {

   //let's register our custom route here
   register_rest_route( 'wp/v2', '/answers/question=(?P<post_parent>\d+)&page=(?P<page>\d+)', array(
    'methods' => 'GET',
    'callback' => 'answers_by_parent_id_callback',
    'args' => [
    'post_parent',
    'page'
     ],
  ));    
}

//here we define our callback function
function answers_by_parent_id_callback( $request ) {

    //let's initialize our data array
    $posts_data = array();

    // Receive and set the page parameter from the $request for pagination 
    $paged = $request->get_param( 'page' );
    $paged = ( isset( $paged ) || ! ( empty( $paged ) ) ) ? $paged : 1; 

    //set a parent-post ID, by which to filter child posts here
    $question_id = $request->get_param( 'post_parent' );

    //if the parent post is not set, return null
    $question_id = ( isset( $question_id ) || ! ( empty($question_id) ) ) ? $question_id : null; 

    // Get the child posts under a specific parent post  
    $posts = get_posts( array(
        'paged' => $paged,                     
        'posts_per_page' => 10, 
        'order' => 'asc', 
        'post_parent' => $question_id,
        'post_type' => 'answer', 
       )
    ); 

// Loop through the posts and push the desired data to the array we've initialized earlier in the form of an object     
foreach( $posts as $post ) {
    $id = $post->ID;  
    $post_author = get_user_by( 'ID', $post->post_author );

    // Get author name, and add it to response directly
    $author_display_name = $post_author->display_name;  

    //get author avatar and add it directly. You need to install a plugin called "Simple Local Avatars" for this to work here => https://wordpress.org/plugins/simple-local-avatars/
    $avatar = get_simple_local_avatar($post_author->ID, 150);       
    $posts_data[] = (object) array( 
        'id' => $id, 
        'slug' => $post->post_name, 
        'type' => $post->post_type,
        'title' => $post->post_title,
        'content' => $post->post_content,
        'question' => $post->post_parent,
        'avatar_url' => $avatar,
        'author_name' => $author_display_name,
        'post_date' => $post->post_date,
       );
     }                  
    return $posts_data;    
}

Now you can querry your child posts (custom post type say answer) based on parent post ID under which they were posted (another custom post type say question). If the Question id is 123, and domain is https://domain.com, then this is your URL from the endpoint above: https://domain.com/wp-json/wp/v2/answers/question=123?page=1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.