25

I want to know if it's possible to get the ID of a page with a specific template. Is this possible to get the ID of a page that assigned to "page-special.php"?

6 Answers 6

53

When a page is created, the assigned template to that page is saved as custom post meta in the same way as custom fields. The meta_key is _wp_page_template and the meta_value will be the page template

You can simply make use of get_pages to retrieve all pages which have a meta_value of the specified template

$pages = get_pages(array(
    'meta_key' => '_wp_page_template',
    'meta_value' => 'page-special.php'
));
foreach($pages as $page){
    echo $page->ID.'<br />';
}

EDIT 23-07-2015

If one just needs the page ids, then you make use of get_posts and then just pass page as post_type and 'idsasfields` value. This will ensure a much faster, much more optimized query as we will only return the post id column in the db and not all of them for the given pages

(Requires PHP 5.4+)

$args = [
    'post_type' => 'page',
    'fields' => 'ids',
    'nopaging' => true,
    'meta_key' => '_wp_page_template',
    'meta_value' => 'page-special.php'
];
$pages = get_posts( $args );
foreach ( $pages as $page ) 
    echo $page . '</br>';
7
  • Hey, Thanks. Isn't a bit too "heavy"? (running through all the pages) Nov 2, 2014 at 8:29
  • Depends on how many pages you have. There is actually no faster native way that I know of to retrieve this data. If you have a lot of pages, I would suggest that you make use of transients to store that data and only flush/delete the transient when a new page is published Nov 2, 2014 at 8:35
  • My pleasure, glad I could help. Enjoy :-) Nov 2, 2014 at 8:44
  • @user3800799 I have updated the post if you are only interested in getting the ids, nothing else Jul 23, 2015 at 10:47
  • You could also use set_transient (codex.wordpress.org/Transients_API) if you don't want to query the database too much. May 19, 2016 at 12:09
5

If your page template resides inside sub-folder, theme-folder/page-templates/page-template.php then you below query will works:

$page_details = get_pages( array(
 'post_type' => 'page',
 'meta_key' => '_wp_page_template',
 'hierarchical' => 0,
 'meta_value' => 'page-templates/page-template.php'
));

This above codes also display sub-pages as well.

Thanks

0
1

The following is a slightly more articulated script that take into account a language, if needed. NOTE that it assumes the usage of Polylang, not WPML.

function get_post_id_by_template($template,$lang_slug = null){
  global $wpdb;
  $wh = ($lang_slug) ? " AND t.slug = %s" : "";

  $query = $wpdb->prepare(
    "SELECT DISTINCT p.ID
    FROM $wpdb->posts p
    INNER JOIN $wpdb->postmeta meta ON meta.post_id = p.ID
    INNER JOIN $wpdb->term_relationships tr ON meta.post_id = tr.object_id
    INNER JOIN $wpdb->term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
    INNER JOIN $wpdb->terms t ON tt.term_id = t.term_id
    WHERE p.post_status = 'publish' AND meta.meta_key = %s AND meta.meta_value = %s" . $wh,
    '_wp_page_template',
    $template,
    $lang_slug
  );

  $ids = $wpdb->get_results($query);

  if($ids && isset($ids[0])){
    $p = $ids[0];
    return $p->ID;
  } else {
    return false;
  }
}// get_post_id_by_template
1

Here is a complete function that works with WPML and Polylang. Credit to https://github.com/cyrale/

/**
* Search for a page with a particular template.
*
* @param string $template Template filename.
* @param array  $args     (Optional) See also get_posts() for example parameter usage.
* @param bool   $single   (Optional) Whether to return a single value.
*
* @return Will be an array of WP_Post if $single is false. Will be a WP_Post object if the page is find, FALSE otherwise
*/
if (!function_exists('get_page_by_template')) {
    function get_page_by_template($template, $args = array(), $single = true) {
        $pages_by_template = wp_cache_get('pages_by_template', 'cyrale');
        if (empty($pages_by_template) || !is_array($pages_by_template)) {
            $pages_by_template = array();
        }
        if (!isset($pages_by_template[$template])) {
            $args = wp_parse_args(array(
                'posts_per_page' => -1,
                'post_type'      => 'page',
                'suppress_filters'  => 0,
                'meta_query'     => array(
                    array(
                        'key'   => '_wp_page_template',
                        'value' => $template,
                    ),
                ),
            ), $args);
            $pages = get_posts($args);
            $pages_by_template[$template]= array(
                'single' => !empty($pages) && is_array($pages) ? reset($pages) : false,
                'pages'  => $pages,
            );
        }
        wp_cache_set('pages_by_template', $pages_by_template, 'cyrale');
        return $pages_by_template[$template][$single ? 'single' : 'pages'];
    }
}
0
function kavkaz_get_page($page_template_filename){
    
    $pages = get_pages( array(
        'meta_key' => '_wp_page_template',
        'meta_value' => $page_template_filename
    ) );

    $url = null;
    
    if(isset($pages[0])) {
        $url = $pages[0]->guid;
    }
    
    return esc_url( $url );
}
2
  • 1
    That looks about the same as the top two answers, a get_pages() search for the meta_key? I also think ->guid is wrong: it might be the URL, but that's not guaranteed. Instead I'd pass the page object (or just the ID) to get_permalink().
    – Rup
    Mar 25, 2022 at 16:23
  • Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
    – Community Bot
    Apr 2, 2022 at 16:41
0

You can query the postmeta table directly:

global $wpdb;
$template = 'page-special';
$sql = "select post_id from {$wpdb->postmeta} where meta_key = '{$template}.php'";
$pages = $wpdb->get_col($sql);
var_dump($pages);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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