Generate Catalog Of Posts Based On Template

Is there a way to print a hierarchy of posts/pages/custom post types based on page template?

EG. I am often asked to review another web site and I’d like a way to ‘see’ all the pages that are assigned to the ‘Newsletter’ PHP template and all the pages assigned to the ‘Product Info’ PHP template.

Read More

Is there a plug-in like that or some code one can recommend?

Related posts

Leave a Reply

2 comments

  1. To get all posts ordered by their template you need two functions: one for the query, and one to add a custom order.

    Get the posts

    function get_posts_by_template()
    {
        add_filter( 'posts_orderby', 'orderby_template' );
    
        $query = new WP_Query(
            array(
                //'meta_key' => '_wp_page_template',
                'post_type' => 'any',
                'orderby'  => 'title',
                'order'    => 'ASC',
                'posts_per_page' => -1, // dangerous
                'meta_query' => array(
                    array(
                        'key' => '_wp_page_template',
                        'value' => '',
                        'compare' => '!='
                    )
                )
            )
        );
    
        if ( empty ( $query->posts ) )
            return FALSE;
    
        return $query->posts;
    }
    

    Change the order

    function orderby_template( $orderby )
    {
        global $wpdb;
    
        remove_filter( current_filter(), __FUNCTION__ );
        $orderby = $wpdb->postmeta . '.meta_value DESC, ' . $orderby;
    
        return $orderby;
    }
    

    For a nice overview we could use something like this:

    function list_posts_by_template()
    {
        $posts = get_posts_by_template();
    
        if ( ! $posts )
            return print 'no posts with a template found';
    
        static $template = '';
    
        foreach ( $posts as $post )
        {
            $post_template = get_post_meta( $post->ID, '_wp_page_template', TRUE ) . '<br>';
    
            if ( $post_template !== $template )
            {
                print "<h2>$post_template</h2>";
                $template = $post_template;
            }
    
            printf(
                '<p><a href="%1$s">%2$s</a></p>',
                get_permalink( $post->ID ),
                esc_html( $post->post_title )
            );
        }
    }
    
  2. I am not sure in what context you need this but assigned page templates are kept in $wpdb->postmeta under the _wp_page_template key so you can do something like …

    $templates = $wpdb->get_results("SELECT * FROM {$wpdb->postmeta} WHERE meta_key = '_wp_page_template'");
    var_dump($templates);
    

    … to get your templates…

    $args = array(
      'post_type' => 'any',
      'meta_query' => array(
        array(
          'key' => '_wp_page_template',
           'compare' => 'EXISTS',
        )
      )
    );
    $t = new WP_Query($args);
    var_dump($t);
    

    … to get posts to compare them against. They are associated by the ID == post_id

    I suppose you could combine the two somewhat with…

    $templates = $wpdb->get_results(
      "SELECT post_id,meta_value,post_title 
      FROM {$wpdb->postmeta} 
      JOIN {$wpdb->posts} ON {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id
      WHERE meta_key = '_wp_page_template'");
    var_dump($templates);
    

    You cannot get the automagically assigned templates this way, if that is what you need.