Skip Navigation

This is the technical support forum for WPML - the multilingual WordPress plugin.

Everyone can read, but only WPML clients can post here. WPML team is replying on the forum 6 days per week, 22 hours per day.

Sun Mon Tue Wed Thu Fri Sat
- - 9:00 – 18:00 9:00 – 18:00 9:00 – 18:00 9:00 – 18:00 9:00 – 18:00
- - - - - - -

Supporter timezone: America/Lima (GMT-05:00)

Tagged: 

This topic contains 16 replies, has 2 voices.

Last updated by Andreas W. 1 day, 23 hours ago.

Assisted by: Andreas W..

Author Posts
January 28, 2025 at 5:48 pm #16643543

lorenzP

Background of the issue:
I am trying to use url_to_postid() to convert a URL to a post ID. For instance, the following call always returns 0: url_to_postid('hidden link'). This happened recently, before there was no such issue. I tried to delete various WPML caches but this made no difference. Link to a page where the issue can be seen: hidden link

Symptoms:
The API should return the post ID, but instead, I got 0.

Questions:
Why does url_to_postid() return 0 for a valid URL in the secondary language?
How can I resolve the issue of url_to_postid() not returning the correct post ID?

January 29, 2025 at 8:23 am #16644795

Marcel
Supporter

Languages: English (English ) German (Deutsch )

Timezone: Europe/Madrid (GMT+01:00)

Hi,

before your ticket is assigned to one of my colleagues, please allow me to walk you through some initial debugging steps. This will help speed up the support process.

I came across an old, archived ticket from you from 2023, where you reported a similar issue with this function while using PHP 8.0:

We found the root cause: the URL parameter was in some occasion a SimpleXMLElement instance and not a string. We added a type cast to a string and it works now fine.

Have you checked if this change is still in place?

Best Regards
Marcel

January 31, 2025 at 5:31 pm #16656847

lorenzP

This is a different issue, the parameter is a string. For instance this call is failing and returns 0 for an existing URL:

url_to_postid('hidden link')

January 31, 2025 at 8:33 pm #16657188

Andreas W.
Supporter

Languages: English (English ) Spanish (Español ) German (Deutsch )

Timezone: America/Lima (GMT-05:00)

Hello,

Each post in each language has its own ID.

You might need to use the following hook in this case:
https://wpml.org/wpml-hook/wpml_object_id/

To get the translated URL please use this hook:
https://wpml.org/wpml-hook/wpml_permalink/

Best regards
Andreas

February 3, 2025 at 2:43 pm #16663422

lorenzP

I think you don't understand our problem. The url_to_postid() API is failing. We have to convert a URL to a post ID and not vice versa. This was working fine in the past and suddenly stopped working.

February 4, 2025 at 5:23 pm #16668063

Andreas W.
Supporter

Languages: English (English ) Spanish (Español ) German (Deutsch )

Timezone: America/Lima (GMT-05:00)

Yes, I understand and this is a native WordPress function that has no idea about the language parameter and how to handle this URL.

This is why you need to use WPML Hooks.

Steps:

Set the Current Language with WPML:
WPML can load different versions of a post based on the current language, so you need to make sure you're getting the correct post ID for the language you want. You can set the current language using WPML's wpml_current_language filter or get the current language using wpml_current_language.

Use url_to_post_id():
url_to_post_id() is a built-in WordPress function that will return the post ID for a given URL. With WPML, you can get the URL of a post in a specific language and pass that URL to url_to_post_id().

Example Code:
Here’s how you can integrate it:

// Use the wpml_current_language hook to get the current language
$current_language = apply_filters( 'wpml_current_language', NULL );

// Get the permalink for a specific post (replace with your post ID)
$post_permalink = get_permalink( $post_id );

// Get the post ID from the URL (this works for the default language, based on permalink)
$post_id_in_default_language = url_to_post_id( $post_permalink );

// Use WPML's filter to get the translated post ID in the current language
$translated_post_id = apply_filters( 'wpml_object_id', $post_id_in_default_language, 'post', false, $current_language );

// $translated_post_id now contains the post ID for the current language
echo $translated_post_id;
February 5, 2025 at 10:46 am #16670338

lorenzP

The code example you provided has a bug, it should be url_to_postid() and not url_to_post_id().

This example however uses the API as we do, first you call url_to_postid() on a URL and then its result is passed to a WPML hook. But as I explained, url_to_postid() returns 0 and therefore the WPML hook cannot improve anything.

In the meantime I had a look at the WPML source code and its url_to_postid filter implementation. I wrote a demo template to further analyze our issue. The following pages work fine:

hidden link
hidden link

But as soon as we have a parent page the translated page returns 0:

hidden link
hidden link

The problem is related to the path handling.

Bildschirmfoto 2025-02-05 um 11.44.53.png
February 5, 2025 at 10:48 am #16670373

lorenzP

Source code of the test page:

'''
<div class="container">
<h1>WPML Tests</h1>

<h2>url_to_postid()</h2>

<?php

// 1) page info
$page_id = $post->ID;
$permalink = get_permalink($page_id);

echo '<div>Post ID: ' . $page_id . '</div>';
echo '<div>Permalink: ' . esc_html($permalink) . '</div>';

// 2) WPML info
$lang = apply_filters('wpml_current_language', NULL);

echo '<div>Current language: ' . esc_html($lang) . '</div>';

// 3) url_to_postid()
$id = url_to_postid($permalink);
$hook = apply_filters('url_to_postid', $permalink);

echo '<div>url_to_post_id(\'' . esc_html($permalink) . '\'): ' . $id . '</div>';
echo '<div>url_to_post_id hook: ' . esc_html($hook) . '</div>';

?>
</div>
'''

February 5, 2025 at 3:30 pm #16671950

Andreas W.
Supporter

Languages: English (English ) Spanish (Español ) German (Deutsch )

Timezone: America/Lima (GMT-05:00)

My apologies for the small bag in the provided snippet. Kindly take note that our supporters are not obligated to provide any custom code solutions. This is something that is usually not supported by our support policy. I provided this snippet voluntarily.

Suggestions:
- pass the wpml_object_id filter to $page_id
- pass the wpml_permalink filter to $permalink
- set the language URL format to "Languages in directories".

February 5, 2025 at 10:34 pm #16673131

lorenzP

Well, I provided a reproducible test case. In addition this error does not occur on our production site. Here the same page works fine:

hidden link

Could you please forward this case to the next support level. Something is broken in WPML and our staging environment contains the new site we want to launch ASAP and got now delayed because of this issue.

February 5, 2025 at 11:26 pm #16673314

Andreas W.
Supporter

Languages: English (English ) Spanish (Español ) German (Deutsch )

Timezone: America/Lima (GMT-05:00)

Can you please first confirm if you followed my suggestion of using the WPML Hooks for this purpose?

I can only escalate an issue to second-tier support if we are handling a bug in WPML that was confirmed.

Please try to recreate the issue using a simple example on the following test site:
hidden link

Make sure to leave me a comment on this ticket once the issue has been recreated and I will take a look into it.

February 6, 2025 at 9:14 pm #16677368

lorenzP

The WPML hooks you suggested are called after the url_to_postid() call and are therefore useless because the API returns 0 which means the URL is invalid but in the URL is correct.

As said from beginning, this issue appeared while editing content on our staging environment. Before it was working fine and on our production environment we are using those APIs for more than 4 years without any issues. I created a test case to easily reproduce it on our staging environment. I guess something in the database is broken. We tried several of the WPML repair functionalities but none of them improved anything. I propose we provide access to a cloned version of our staging site to analyze the database.

February 6, 2025 at 9:30 pm #16677390

Andreas W.
Supporter

Languages: English (English ) Spanish (Español ) German (Deutsch )

Timezone: America/Lima (GMT-05:00)

You need to call the hooks before calling the function.

The url_to_postid() returns the ID of the post.

I have no issue taking a look at the site, but I do honestly not think that this is necessary. I already provided a solution for the issue so that you can obtain the correct ID per language:

// Use the wpml_current_language hook to get the current language
$current_language = apply_filters( 'wpml_current_language', NULL );
 
// Get the permalink for a specific post (replace with your post ID)
$post_permalink = get_permalink( $post_id );
 
// Get the post ID from the URL (this works for the default language, based on permalink)
$post_id_in_default_language = url_to_post_id( $post_permalink );
 
// Use WPML's filter to get the translated post ID in the current language
$translated_post_id = apply_filters( 'wpml_object_id', $post_id_in_default_language, 'post', false, $current_language );
 
// $translated_post_id now contains the post ID for the current language
echo $translated_post_id;

Take kindly note that our supporters are not expected to provide such a custom code solution. I am doing this on a voluntary base.

February 6, 2025 at 9:46 pm #16677418

lorenzP

Well, your example only calls one hook before the url_to_postid() call, namely 'wpml_current_language' which returns the current language. This calls does nothing else and is not needed.

Please, please, get me some professional support now.

February 6, 2025 at 9:58 pm #16677426

Andreas W.
Supporter

Languages: English (English ) Spanish (Español ) German (Deutsch )

Timezone: America/Lima (GMT-05:00)

Let me explain the approach in detail:

You are using a native WordPress function that is not aware of different languages on the website to use the URL of a page or post as an argument and to return the ID of each post or page.

This is why you need to use wpml_currenct_language to get the current language of the website.

// Use the wpml_current_language hook to get the current language
$current_language = apply_filters( 'wpml_current_language', NULL );

Then we pass $current_language to wpml_permalink to the permalink for each post to each language:

// Get the permalink for a specific post (replace with your post ID)
$post_permalink = get_permalink( $post_id );

Then we use this $post_permalink to pass it as URL to url_to_post_id().

// Get the post ID from the URL (this works for the default language, based on permalink)
$post_id_in_default_language = url_to_post_id( $post_permalink );

Finally, we hold the post_id inside $post_id_in_default_language and we pass it to wpml_object_id which will get the correct ID per language, and at the same time we pass $current_language.

// Use WPML's filter to get the translated post ID in the current language
$translated_post_id = apply_filters( 'wpml_object_id', $post_id_in_default_language, 'post', false, $current_language );

This means, $translated_post_id will now return the original post ID in site's default language and any translated post ID in second languages.