post_type_link │ хук-фильтр │ WP 3.0.0

Позволяет изменить ссылку на кастомный пост.

Callback должен вернуть URL.

Фильтр вызывается в конце get_post_permalink(), в файле wp-includes/link-template.php. get_permalink() также использует эту функцию для произвольных типов записей.

При получении ссылок через get_permalink() используется:

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

add_filter( 'post_type_link', 'wp_kama_post_type_link_filter', 10, 4 );

/**
 * Function for `post_type_link` filter-hook.
 * 
 * @param string  $post_link The post's permalink.
 * @param WP_Post $post      The post in question.
 * @param bool    $leavename Whether to keep the post name.
 * @param bool    $sample    Is it a sample permalink.
 *
 * @return string
 */
function wp_kama_post_type_link_filter( $post_link, $post, $leavename, $sample ){
	// filter...
	return $post_link;
}
$post_link(строка)
Постоянная ссылка записи.
Может быть ЧПУ или URL с GET-параметрами: фильтр применяется в обоих случаях.
$post(WP_Post)
Объект записи, для которой формируется ссылка.
Проверяйте $post->post_type, чтобы ограничить действие нужным типом.
$leavename(логический)
Сохранять ли в ЧПУ плейсхолдер %имя_типа% вместо подстановки слага записи.
Например, при true ссылка может содержать /books/%book%/.
При false WordPress подставляет слаг, а для иерархического типа - путь с родительскими записями.
При формировании обычной ссылки с GET-параметрами этот флаг не влияет на результат.
$sample(логический)
Формируется ли образец постоянной ссылки, например для редактора. Это не проверка режима предпросмотра is_preview().
При true WordPress может использовать ЧПУ даже для записи, которой обычно нужна простая ссылка.
get_sample_permalink() временно меняет статус и слаг объекта записи. Поэтому для исключения образцов ссылок проверяйте $sample, а не только $post->post_status.

Примеры

#1 Внешняя ссылка из метаполя

Для опубликованных записей типа resource заменим ссылку значением метаполя external_url.

add_filter( 'post_type_link', 'my_resource_external_link', 10, 4 );

function my_resource_external_link( $post_link, $post, $leavename, $sample ) {
	if (
		'resource' !== $post->post_type
		|| 'publish' !== $post->post_status
		|| $leavename
		|| $sample
		|| 'link' !== get_post_format( $post )
	) {
		return $post_link;
	}

	$url = get_post_meta( $post->ID, 'external_url', true );
	$url = is_string( $url ) ? esc_url_raw( $url, [ 'http', 'https' ] ) : '';

	return $url ?: $post_link;
}

Замена работает только для формата записи link. Тип записи должен поддерживать post-formats, а тема - формат link, если он выбирается в редакторе.

Редирект со старого формата нужно выполнять отдельно на template_redirect. Проверяйте тот же тип, статус, формат и метаполе; предпросмотр исключайте через is_preview().

Для перехода на внешний сайт используется wp_redirect(), после успешного вызова нужен exit.

#2 Перенос GET-параметра в ссылку

Добавим текущий utm_source в ссылки записей типа book. Переносим только выбранный параметр, чтобы случайно не добавить служебные параметры запроса.

add_filter( 'post_type_link', 'my_book_tracking_link', 10, 4 );

function my_book_tracking_link( $post_link, $post, $leavename, $sample ) {
	if ( 'book' !== $post->post_type || $leavename || $sample ) {
		return $post_link;
	}

	if ( ! ( $_GET['utm_source'] ?? '' ) ) {
		return $post_link;
	}

	$source = sanitize_text_field( wp_unslash( $_GET['utm_source'] ) );

	return add_query_arg( 'utm_source', rawurlencode( $source ), $post_link );
}

add_query_arg() не экранирует результат для HTML. При самостоятельном выводе ссылки в href используйте esc_url().

Учтите, что фильтр действует на все соответствующие вызовы получения ссылки, включая вызовы вне шаблона. Если параметр нужен только конкретной кнопке, добавляйте его при формировании этой кнопки.

#3 Удаление префикса типа записи

Например, можно изменить /team-member/jack/ на /jack/. Однако одной замены строки в post_type_link недостаточно.

Нужно также научить WordPress искать запись нужного типа по новому адресу. Если правила перезаписи уже разобрали адрес в переменную name, основной запрос можно уточнить через pre_get_posts: найти запись с помощью get_page_by_path() и установить её post_type.

Такую обработку ограничивают основным запросом на фронтенде, без явно заданного post_type. Если адрес разобран иначе, например в pagename, потребуется отдельная обработка. Также нужно разрешить конфликты одинаковых слагов со страницами и обычными записями. Универсально удалять префикс без учёта структуры сайта нельзя.

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

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

Где вызывается хук

get_post_permalink()
post_type_link
wp-includes/link-template.php 375
return apply_filters( 'post_type_link', $post_link, $post, $leavename, $sample );

Где используется хук в WordPress

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