apply_filters( ‘post_type_link’, string $post_link, WP_Post $post, bool $leavename, bool $sample )

Filters the permalink for a post of a custom post type.

Parameters

$post_linkstring
The post’s permalink.
$postWP_Post
The post in question.
$leavenamebool
Whether to keep the post name.
$samplebool
Is it a sample permalink.

More Information

post_type_link is a filter applied to the permalink URL for a post or custom post type prior to being returned by the function get_post_permalink() .

Source

return apply_filters( 'post_type_link', $post_link, $post, $leavename, $sample );

Changelog

VersionDescription
3.0.0Introduced.

User Contributed Notes

  1. Skip to note 4 content

    External Link for custom post type using meta field and post format ( Link ).

    if ( ! function_exists( 'set_external_url_post_link' ) ):
    	function set_external_url_post_link( $post_link, $post ) {
    		if ( 'custom_post_type' === $post->post_type ) {
    			$external_url  = get_post_meta( $post->ID, 'MY_META_KEY', true );
    			if ( 'link' == get_post_format( $post->ID ) && ! empty( $external_url ) ) {
    				return $external_url;
    			}
    		}
    		return $post_link;
    	}
    	add_filter( 'post_type_link', 'set_external_url_post_link', 10, 2 );
    endif;
    
    if ( ! function_exists( 'redirect_url_post_link' ) ):
    	function redirect_url_post_link() {
    		global $post;
    		if ( is_single() && ( 'custom_post_type' === get_post_type( $post ) ) ) {
    			$external_url  = get_post_meta( $post->ID, 'MY_META_KEY', true );
    			if ( 'link' == get_post_format( $post->ID ) && ! empty( $external_url ) ) {
    				wp_redirect( $external_url );
    				exit();
    			}
    		}
    	}
    	add_action('template_redirect', 'redirect_url_post_link');
    endif;
  2. Skip to note 5 content

    Example migrated from Codex:

    Append the query string for the custom post type ‘my_custom_post_type’ permalink URLs ( uses add_query_arg() and get_post_type() ):

    function append_query_string( $url, $post ) {
        if ( 'my_custom_post_type' == get_post_type( $post ) ) {
            return add_query_arg( $_GET, $url );
        }
        return $url;
    }
    add_filter( 'post_type_link', 'append_query_string', 10, 2 );
  3. Skip to note 6 content

    Here’s a practical example of using the post_type_link filter to remove a custom post type slug (e.g., team-member) from its permalink, and adjusting the main query to recognize those URLs correctly. (See: pre_get_posts)

    // Remove 'wpdocs-cpt' slug from permalinks
    function wpdocs_remove_team_member_slug_only( $post_link, $post ) {
        if ( 'wpdocs-cpt' !== $post->post_type || 'publish' !== $post->post_status ) {
            return $post_link;
        }
    
        // Return URL without the CPT slug
        return home_url( '/' . $post->post_name . '/' );
    }
    add_filter( 'post_type_link', 'wpdocs_remove_cpt_slug_only', 10, 2 );
    
    // Adjust main query to detect wpdocs-cpt posts
    function wpdocs_fix_cpt_query( $query ) {
        if ( ! $query->is_main_query() || is_admin() || ! empty( $query->query_vars['post_type'] ) ) {
            return;
        }
    
        if ( isset( $query->query_vars['name'] ) ) {
            // Check if the slug belongs to a team-member post
            $cpt = get_page_by_path( $query->query_vars['name'], OBJECT, 'wpdocs-cpt' );
    
            if ( $cpt ) {
                $query->set( 'post_type', 'wpdocs-cpt' );
            }
        }
    }
    add_action( 'pre_get_posts', 'wpdocs_fix_cpt_query' );

You must log in before being able to contribute a note or feedback.