Using get_pages to exclude using wp_list_pages() doesn't work

Viewed 198

Below you will see my code that currently fails to exclude pages that have "hide" set as the edit_screen_sitemap value.

I've included all of the var_dump's along the way and the Wordpress warnings displayed when using WP_DEBUG.

    <?php
    $excludedPosts = get_pages(array('meta_key'=>'edit_screen_sitemap','meta_value'=>'hide'));
    var_dump($excludedPosts);
    /*
        array(1) { [0]=> object(WP_Post)#5486 (28) { ["ID"]=> int(4002) ["post_author"]=> string(1) "1" ["post_date"]=> string(19) "2017-09-12 17:58:09" ["post_date_gmt"]=> string(19) "2017-09-12 16:58:09" ["post_content"]=> string(0) "" ["post_title"]=> string(48) "Thank You for Signing Up For Your Boiler Service" ["post_excerpt"]=> string(0) "" ["post_status"]=> string(7) "publish" ["comment_status"]=> string(6) "closed" ["ping_status"]=> string(6) "closed" ["post_password"]=> string(0) "" ["post_name"]=> string(12) "10-thank-you" ["to_ping"]=> string(0) "" ["pinged"]=> string(0) "" ["post_modified"]=> string(19) "2020-10-27 00:47:53" ["post_modified_gmt"]=> string(19) "2020-10-27 00:47:53" ["post_content_filtered"]=> string(0) "" ["post_parent"]=> int(0) ["guid"]=> string(43) "http://www.taylorpickering.com/?page_id=249" ["menu_order"]=> int(8) ["post_type"]=> string(4) "page" ["post_mime_type"]=> string(0) "" ["comment_count"]=> string(1) "0" ["filter"]=> string(3) "raw" ["meta_id"]=> string(4) "6328" ["post_id"]=> string(4) "4002" ["meta_key"]=> string(19) "edit_screen_sitemap" ["meta_value"]=> string(4) "hide" } }
    */

    $excludeArray = array();

    foreach ($excludedPosts as $excludedPost){
        setup_postdata( $excludedPost );
        $excludeArray[] = $post->ID;
    }

    var_dump($excludeArray);
    /*
        array(1) { [0]=> int(3986) }
    */

    $args = array(
        'post_status'=>'publish',
        'sort_column'=>'name',
        'title_li'=>'',
        'exclude'=> $excludeArray
    );

    var_dump($args);
    /*
        array(4) { ["post_status"]=> string(7) "publish" ["sort_column"]=> string(4) "name" ["title_li"]=> string(0) "" ["exclude"]=> array(1) { [0]=> string(0) "" } }
    */

    wp_list_pages($args);

    /* Wordpress Warnings
        Warning: explode() expects parameter 2 to be string, array given in /wp-includes/post-template.php on line 1294
        Warning: implode(): Invalid arguments passed in /wp-includes/post-template.php on line 1303
    */
    ?>

UPDATE

After reading some more I noticed 'exclude' only accepts comma separated strings, therefore I have added the following code before defining the $args:

$excludeArray = implode(",",$excludeArray);
var_dump($excludeArray);
/*
string(9) "3986,3986"
*/

Which turns it into a comma separated string, but still no luck.

2 Answers

So the issue was actually found after adding a 2nd page into the hiding equation and relates only to the foreach loop:

foreach ($excludedPosts as $excludedPost){
    setup_postdata( $excludedPost );
    $excludeArray[] = $post->ID;
}

Using the setup_postdata as I had clearly wrongly researched meant all IDs thereafter were the same, I simply updated the loop to be:

foreach ($excludedPosts as $excludedPost){
    $excludeArray[] = $excludedPost->ID;
}

And it now works as expected!

Late answer but you can even clean up the get_pages and the loop to parse for ids like below:

<?php
  // fetch posts as an array of ids
  $excludedPostsArray = get_posts(array(
    // that are pages
    'post_type' => 'page',
    'meta_key' => 'edit_screen_sitemap', 
    'meta_value' => 'hide',
    // only return id field
    'fields' => 'ids'
  ));

  // join array of ids into comma sep string e.g. 1, 2, 3
  $excludeIds = implode(', ', $excludedPostsArray);

  // do other stuff
  $args = array(
    'post_status' => 'publish',
    'sort_column' => 'name',
    'title_li' => '',
    'exclude' => $excludeIds
  );
?>
Related