get_page_by_path()WP 2.1.0

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

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

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

Для древовидных типов записей в первый параметр нужно указать полный путь! Если указать только 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.9

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";
	$cached    = wp_cache_get_salted( $cache_key, 'post-queries', $last_changed );
	if ( false !== $cached ) {
		// Special case: '0' is a bad `$page_path`.
		if ( '0' === $cached || 0 === $cached ) {
			return null;
		} 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 );

	$found_id = 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 !== (int) $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 === (int) $p->post_parent
				&& count( $revparts ) === $count + 1
				&& $p->post_name === $revparts[ $count ]
			) {
				$found_id = $page->ID;
				if ( $page->post_type === $post_type ) {
					break;
				}
			}
		}
	}

	// We cache misses as well as hits.
	wp_cache_set_salted( $cache_key, $found_id, 'post-queries', $last_changed );

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

	return null;
}