get_page_by_path()WP 2.1.0

Получает запись по указанному пути этой страницы: parent-page/sub-page. Результат кэшируется.

Можно указать ярлык (имя, post_name, slug) для не древовидных типов записей. Т.е. так можно получить пост по имени.

Можно указать с каким типом записи работать, по умолчанию page.

Для древовидных типов записей в первый параметр нужно указать полный путь! Например, если указать только slug и это дочерняя страница, то функция не найдет страницу. Например, у записи такой URL /parent_name/child_name, если указать только имя child_name, то функция не найдет пост.

Эта функция лежит в основе распознования текущего запроса для постоянных страниц на базе ЧПУ: запросов вида: index.php?pagename=parent-page/sub-page.

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

1 раз — 0.000868 сек (медленно) | 50000 раз — 0.59 сек (очень быстро) | PHP 7.1.2, WP 4.7.3

Хуков нет.

Возвращает

WP_Post|Массив|null.

  • WP_Post или массив при успехе.
  • null при ошибке.

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

get_page_by_path( $page_path, $output, $post_type );
$page_path(строка) (обязательный)
Путь страницы. Для не древовидных записей можно указать ярлык (slug). Слэши / на концах срезаются.
$output(строка)

В каком виде нужно получить результат:

  • OBJECT - возвращать как объект;
  • ARRAY_N - возвращать как нумерованный массив;
  • ARRAY_A - возвращать как ассоциативный массив.

По умолчанию: OBJECT

$post_type(строка/массив)

Название типа записи. Для страниц это 'page'.

  • Если указать несколько типов записей или один в массиве: ['post', 'page'] или ['post'], то поиск будет вестись именно по указанным типам записей.
  • Если указать тип записи в виде строки, то к нему будет также добавлен тип записи attachment.

По умолчанию: 'page' (впоследствии становится 'page, attachment')

Примеры

0

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

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

$page = get_page_by_path( 'parent-page/sub-page' );

// или так
$page = get_page_by_path( '/parent-page/sub-page/' );

print_r( $page );

ВАЖНО! Если указать просто имя страницы, то функция ничего не вернет

$page = get_page_by_path( 'sub-page' ); //> NULL

Однако, если страница не дочерняя, то нужно указывать просто имя страницы - ярлык (slug).

$page = get_page_by_path( 'page-name' ); //> WP_Post{ ... }
0

#2 Использование с новыми типами записей

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

// Правильный вариант
$page = get_page_by_path( 'lada', OBJECT, 'car' );

// НЕ правильный (ничего не вернет)
$page = get_page_by_path( 'car/lada', OBJECT, 'car' );
Авто-добавление типа attachment
// запрос будет: post_type IN ( 'car', 'attachment' )
$page = get_page_by_path( 'lada', OBJECT, 'car' );

// запрос будет: post_type IN ( 'car' )
$page = get_page_by_path( 'lada', OBJECT, ['car'] );
Получение последний части пути

Чтобы получить последнюю часть пути можно использовать функции basename() и untrailingslashit():

$page_path = 'car/lada/';
$post_name = basename( untrailingslashit( $page_path ) );
$page = get_page_by_path( $post_name , OBJECT, 'car');

Заметки

  • Global. wpdb. $wpdb WordPress database abstraction object.

Список изменений

С версии 2.1.0 Введена.

Код get_page_by_path() WP 6.5.2

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, 'post-queries' );
	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         = array_map( 'sanitize_title_for_query', $parts );
	$escaped_parts = esc_sql( $parts );

	$in_string = "'" . implode( "','", $escaped_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 ( 0 != $p->post_parent && isset( $pages[ $p->post_parent ] ) ) {
				++$count;
				$parent = $pages[ $p->post_parent ];
				if ( ! isset( $revparts[ $count ] ) || $parent->post_name != $revparts[ $count ] ) {
					break;
				}
				$p = $parent;
			}

			if ( 0 == $p->post_parent && count( $revparts ) === $count + 1 && $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, 'post-queries' );

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

	return null;
}