get_page_by_path

Получает страницу по указанному пути этой страницы: parent-page/sub-page. Вместо пути может быть просто ярлык страницы (slug). Указав параметр $post_type можно получить запись любого типа, не только page.

Запрос создаваемый функцией очень похож на такой запрос: index.php?pagename=parent-page/sub-page.

Чтобы получить запись по заголовку, используйте get_page_by_title()

Поле post_name имеет индекс в таблице wp_posts, поэтому такой запрос должен быть быстрым.
✈ 1 раз = 0.001006с = очень медленно | 50000 раз = 29.10с = медленно PHP 7.0.2, WP 4.4.1

Хуков нет.

Возвращает

WP_Post/массив/void. Объект WP_Post.

Использование

get_page_by_path( $page_path, $output, $post_type );
$page_path(строка) (обязательный)
Путь страницы, можно указать ярлык (slug).
$output(строка)
В каком виде нужно получить результат:
OBJECT – возвращать как объект;
ARRAY_N – возвращать как нумерованный массив;
ARRAY_A – возвращать как ассоциативный массив.
По умолчанию: OBJECT
$post_type(строка/массив)
Название типа записи. Для страниц это ‘page’. Можно указать несколько в массиве: array('post', 'page');.
По умолчанию: ‘page’

Примеры

#1 Получим страницу указав её путь

Предположим у нас есть дочерняя страница, к которой мы обращаемся по такому URL site.ru/parent-page/sub-page: parent-page/sub-page – это путь страницы. Теперь, где-то в коде получим эту страницу.

$page = get_page_by_path('parent-page/sub-page');
// используем $page

Если это не дочерняя страница, то нужно указывать имя страницы – ярлык slug.

#2 Как использовать функцию для новых типов записей

Если вы создали новый тип записи, то путь до такой записи, обычно претворен названием типа записи. Например наш тип записи называется car, то URL конкретной записи будет: site.ru/car/lada. Чтобы получить такую запись, нужно использовать только её ярлык:

<?php
function get_page_by_path( $page_path, $output = OBJECT, $post_type = 'page' ) {
	global $wpdb;

	$last_changed = wp_cache_get_last_changed( 'posts' );

	$hash = md5( $page_path . serialize( $post_type ) );
	$cache_key = "get_page_by_path:$hash:$last_changed";
	$cached = wp_cache_get( $cache_key, 'posts' );
	if ( false !== $cached ) {
		// Special case: '0' is a bad `$page_path`.
		if ( '0' === $cached || 0 === $cached ) {
			return;
		} else {
			return get_post( $cached, $output );
		}
	}

	$page_path = rawurlencode(urldecode($page_path));
	$page_path = str_replace('%2F', '/', $page_path);
	$page_path = str_replace('%20', ' ', $page_path);
	$parts = explode( '/', trim( $page_path, '/' ) );
	$parts = esc_sql( $parts );
	$parts = array_map( 'sanitize_title_for_query', $parts );

	$in_string = "'" . implode( "','", $parts ) . "'";

	if ( is_array( $post_type ) ) {
		$post_types = $post_type;
	} else {
		$post_types = array( $post_type, 'attachment' );
	}

	$post_types = esc_sql( $post_types );
	$post_type_in_string = "'" . implode( "','", $post_types ) . "'";
	$sql = "
		SELECT ID, post_name, post_parent, post_type
		FROM $wpdb->posts
		WHERE post_name IN ($in_string)
		AND post_type IN ($post_type_in_string)
	";

	$pages = $wpdb->get_results( $sql, OBJECT_K );

	$revparts = array_reverse( $parts );

	$foundid = 0;
	foreach ( (array) $pages as $page ) {
		if ( $page->post_name == $revparts[0] ) {
			$count = 0;
			$p = $page;

			/*
			 * Loop through the given path parts from right to left,
			 * ensuring each matches the post ancestry.
			 */
			while ( $p->post_parent != 0 && isset( $pages[ $p->post_parent ] ) ) {
				$count++;
				$parent = $pages[ $p->post_parent ];
				if ( ! isset( $revparts[ $count ] ) || $parent->post_name != $revparts[ $count ] )
					break;
				$p = $parent;
			}

			if ( $p->post_parent == 0 && $count+1 == count( $revparts ) && $p->post_name == $revparts[ $count ] ) {
				$foundid = $page->ID;
				if ( $page->post_type == $post_type )
					break;
			}
		}
	}

	// We cache misses as well as hits.
	wp_cache_set( $cache_key, $foundid, 'posts' );

	if ( $foundid ) {
		return get_post( $foundid, $output );
	}
}