Obtener el ID de página por plantilla
Quiero saber si es posible obtener el ID de una página con una plantilla específica. ¿Es posible obtener el ID de una página que está asignada a "page-special.php"?

Cuando se crea una página, la plantilla asignada a esa página se guarda como metadato personalizado (post meta) de la misma manera que los campos personalizados. La clave meta_key
es _wp_page_template
y el valor meta_value
será la plantilla de página.
Puedes simplemente utilizar get_pages
para recuperar todas las páginas que tengan un meta_value
de la plantilla especificada:
$pages = get_pages(array(
'meta_key' => '_wp_page_template',
'meta_value' => 'page-special.php'
));
foreach($pages as $page){
echo $page->ID.'<br />';
}
ACTUALIZACIÓN 23-07-2015
Si solo necesitas los IDs de las páginas, entonces puedes usar get_posts
y pasar page
como post_type
y 'idscomo valor de
fields`. Esto asegurará una consulta mucho más rápida y optimizada, ya que solo devolverá la columna de ID de publicación en la base de datos y no todos los campos para las páginas solicitadas.
(Requiere 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>';

Hola, gracias. ¿No es un poco "pesado"? (recorriendo todas las páginas)

Depende de cuántas páginas tengas. Realmente no conozco una forma nativa más rápida de obtener estos datos. Si tienes muchas páginas, te sugeriría que utilices transients para almacenar esa información y solo actualices/elimines el transient cuando se publique una nueva página

@user3800799 He actualizado la publicación si solo estás interesado en obtener los IDs, nada más

También podrías usar set_transient
(https://codex.wordpress.org/Transients_API) si no quieres consultar demasiado la base de datos.

@ChrisAndersson A menos que tengas cientos de páginas, configurar un transient será bastante inútil aquí. Mi código realiza solo una consulta a la base de datos súper rápida ya que solo consultamos IDs de publicaciones, lo que aumenta drásticamente el rendimiento. Los transients realizan dos llamadas a la base de datos cada vez que se carga una página, aunque podría ser un poco más rápido. Los transients solo son útiles para operaciones costosas

Si tu plantilla de página reside dentro de una subcarpeta, como theme-folder/page-templates/page-template.php, entonces la siguiente consulta funcionará:
$page_details = get_pages( array(
'post_type' => 'page',
'meta_key' => '_wp_page_template',
'hierarchical' => 0,
'meta_value' => 'page-templates/page-template.php'
));
El código anterior también muestra las subpáginas.
Gracias

Aquí hay una función completa que funciona con WPML y Polylang. Créditos a https://github.com/cyrale/
/**
* Busca una página con una plantilla específica.
*
* @param string $template Nombre del archivo de plantilla.
* @param array $args (Opcional) Ver también get_posts() para ejemplo de uso de parámetros.
* @param bool $single (Opcional) Si se debe devolver un solo valor.
*
* @return Será un array de WP_Post si $single es false. Será un objeto WP_Post si se encuentra la página, FALSE en caso contrario
*/
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'];
}
}

El siguiente es un script un poco más articulado que tiene en cuenta un idioma, si es necesario. NOTA: asume el uso de Polylang, no 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

function kavkaz_get_page($page_template_filename){
// Obtener páginas con la plantilla especificada
$pages = get_pages( array(
'meta_key' => '_wp_page_template',
'meta_value' => $page_template_filename
) );
$url = null;
// Si existe al menos una página con esa plantilla
if(isset($pages[0])) {
$url = $pages[0]->guid;
}
// Retornar la URL escapada
return esc_url( $url );
}

Eso parece muy similar a las dos respuestas principales, ¿una búsqueda con get_pages() para el meta_key? También creo que ->guid está mal: podría ser la URL, pero eso no está garantizado. En su lugar, pasaría el objeto de página (o solo el ID) a get_permalink().

Tu respuesta podría mejorarse con información adicional de apoyo. Por favor, [edita] para añadir más detalles, como citas o documentación, para que otros puedan confirmar que tu respuesta es correcta. Puedes encontrar más información sobre cómo escribir buenas respuestas en el centro de ayuda.
