Question:

How to filter to output of the get_permalink() function

John: 5 days ago

I know how to filter the output of the function the_permalink - it is like this:

add_filter('the_permalink', 'my_the_permalink');
function my_the_permalink($url) {
    return 'http://mysite/my-link/';
}

And it works when I use it like: <?PHP the_permalink($id); ?>, but I wanted to change the link returned by get_permalink($id) function. And this filter doesn't affect the returned permalink in that case.

I was trying to catch it with:

add_filter('post_link', 'my_get_permalink', 10, 3);
function my_get_permalink($url, $post, $leavename=false) {
    return 'http://mysite/my-link/';
}

But this filter isn't fired for the get_permalink(). So how can I alter the links returned by the get_permalink()?

Answer:
Jace: 5 days ago

Note that post_link filter is only for the post post type.

For other post types these filters are available:

  • post_type_link (https://developer.wordpress.org/reference/hooks/post_type_link/) for custom post types
  • page_link (https://developer.wordpress.org/reference/hooks/page_link/) for page
  • attachment_link (https://developer.wordpress.org/reference/hooks/attachment_link/) for attachment

The get_permalink()function is actually a wrapper for:

  • get_post_permalink()
  • get_attachement_link()
  • get_page_link()

in those cases.

Here's a way (untested) to create a custom wpse_link filter for all the above cases of get_permalink():

foreach( [ 'post', 'page', 'attachment', 'post_type' ] as $type )
{
    add_filter( $type . '_link', function ( $url, $post_id, ? bool $sample = null ) use ( $type )
    {
        return apply_filters( 'wpse_link', $url, $post_id, $sample, $type );
    }, 9999, 3 );
}

where we can now filter all cases with:

add_filter( 'wpse_link', function(  $url, $post_id, $sample, $type )
{
    return $url;
}, 10, 4 );