I'm using a custom function to add .html to my custom posts & pages, working with WPML.

This script is creating a bug on ACF relationship field permalink.

My custom function :

function custom_post_permalink ($post_link) {
    global $post;
    if($post) {
        $type = get_post_type($post->ID);
        $post_type_data = get_post_type_object( $type );
        $post_type_slug = $post_type_data->rewrite['slug'];
        $post_type_slug_translated = apply_filters( 'wpml_get_translated_slug', $post_type_slug, $type);
        $translated_home_url = apply_filters( 'wpml_home_url', home_url());
        $be_current_lang = apply_filters( 'wpml_current_language', NULL );
            return $translated_home_url . $post_type_slug_translated . '/' . $post->post_name . '.html';
        } else {    
        return $translated_home_url .'/'. $post_type_slug_translated . '/' . $post->post_name . '.html';
add_filter('post_type_link', 'custom_post_permalink');

So when i query my posts/pages/customs posts and i want to display the relationship pages, every data display well.


get_the_permalink( $event_city->ID )

that display the curent page link, or the link of the item in the loop. Not the one of relationship. ( so you have good title link, and wrong url )

nb : if i output $event_city->ID i have the ID of the relationship field, and as i say, it works well with get_the_title( $event_city->ID )

nb2 : i have try with get_permalink, get_post_permalink, and get_the_permalink, same result.

if i deactivate my function, everything works well.

But i can not figure what make this trouble.

1 Answer 1


You shouldn't rely on the global $post variable for filters like this.

In your example you're passing $event_city->ID to get_the_permalink(). This implies that the $event_city post is not for the same post as the current $post object. This is normal. Sometimes you want to use a function like get_the_title() or get_the_permalink() without changing the global $post variable.

At some stage the value of get_the_permalink() is passed through the post_type_link filter. The problem then is that your custom_post_permalink() function completely disregards the specific post that the link was requested for ($event_city), and instead only uses the global post variable. This means that when the get_the_permalink() function is called outside the loop, it will only ever retrieve a link based on the current post in the loop.

So how do we use the correct post in the filter? As documented, post_type_link filter callbacks receive a post object as the 2nd argument. This object will represent the post that the link was requested for in get_the_permalink(). So you need to use that object in your function:

function custom_post_permalink( $post_link, $post ) { // Accept $post argument.
    $post_type                 = get_post_type( $post->ID ); // $post now refers to the one passed as an argument.
    $post_type_data            = get_post_type_object( $post_type );
    $post_type_slug            = $post_type_data->rewrite['slug'];
    $post_type_slug_translated = apply_filters( 'wpml_get_translated_slug', $post_type_slug, $post_type );
    $translated_home_url       = apply_filters( 'wpml_home_url', home_url() );
    $be_current_lang           = apply_filters( 'wpml_current_language', NULL );

    if ( $be_current_lang === 'fr' ) {
        return $translated_home_url . $post_type_slug_translated . '/' . $post->post_name . '.html';
    } else {
        return $translated_home_url . '/' . $post_type_slug_translated . '/' . $post->post_name . '.html';
add_filter( 'post_type_link', 'custom_post_permalink', 10, 2 ); // Specify that we're accepting 2 arguments.

Whenever possible you should not rely on the global $post variable. If the filter or action hook passed a post object to the callback function, always use that. If you had filtered the_title the same way, relying on global $post, you'd be having the exact same issue (in that case the filter gets the post ID, which you can use to get the object).

  • You're a GENIUS ! explained like this, it seems so logic... Thank you very much.
    – Gregory
    Jun 7, 2019 at 13:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.