admin管理员组

文章数量:1122846

the situation :

my settings > permalinks are sets on post name, but sometimes anyway a post url is using the query post id :

/?p=4348 instead of

I identified in which situation it happens : when the post status is draft instead of publish. I let the connected users see their page in draft, but in this case the url does not uses the post_name anymore, but a query with the post_id.

the problem :

I want to be safe from this when I'm in production, here is the problem it causes :

On posts i have links like <a href="?action=my_action"></a>, they are supposed to produce this kind of url :

https://my_website/my_post/?action=my_action

but instead, if the page url was using the query and not the post_name, i get this url :

https://my_website/?action=my_action

because the new query replace the previous one. So i loose the information of the page on which I want to execute the action.

solutions ?

I cannot dynamically create the link to add the information in the query for example (I'm not the one creating the front, and the links are created with a front builder, divi)

I've tried to get the current url, check if it uses the wrong pattern, and in that case redirect to the right pattern, but I could not. First I created the right url with home_url('path/'.$post->post_name), then i wanted to compare it to the current url, but I could not reliably find it ? I've tried with get_permalink();, global $wp; $wp->request;, and get_query_vars(), but it failed.

I also tried to check from which page the url comes, but i use the request referer for that and I think I cannot rely on it ? Anyway this option is not optimal since sometime i cannot differentiate the action by the page i come from, in case there is action on both pages.

the situation :

my settings > permalinks are sets on post name, but sometimes anyway a post url is using the query post id :

https://my_website.com/?p=4348 instead of https://my_website.com/my_post

I identified in which situation it happens : when the post status is draft instead of publish. I let the connected users see their page in draft, but in this case the url does not uses the post_name anymore, but a query with the post_id.

the problem :

I want to be safe from this when I'm in production, here is the problem it causes :

On posts i have links like <a href="?action=my_action"></a>, they are supposed to produce this kind of url :

https://my_website/my_post/?action=my_action

but instead, if the page url was using the query and not the post_name, i get this url :

https://my_website/?action=my_action

because the new query replace the previous one. So i loose the information of the page on which I want to execute the action.

solutions ?

I cannot dynamically create the link to add the information in the query for example (I'm not the one creating the front, and the links are created with a front builder, divi)

I've tried to get the current url, check if it uses the wrong pattern, and in that case redirect to the right pattern, but I could not. First I created the right url with home_url('path/'.$post->post_name), then i wanted to compare it to the current url, but I could not reliably find it ? I've tried with get_permalink();, global $wp; $wp->request;, and get_query_vars(), but it failed.

I also tried to check from which page the url comes, but i use the request referer for that and I think I cannot rely on it ? Anyway this option is not optimal since sometime i cannot differentiate the action by the page i come from, in case there is action on both pages.

Share Improve this question edited Apr 4, 2024 at 17:24 hugogogo asked Apr 4, 2024 at 16:38 hugogogohugogogo 1113 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

I found two possible solutions to my problem :

1. the link to the post should not use permalink

the problem is actually that a draft post has a permalink with its post_id instead of post_name, as explained here : How to make draft posts or posts in review accessible via full url / slug?

so, in my case i could find where the link is generated, and it was getting the link with get_permalink() which will return the url with post_id if the post is a draft. So instead i now use home_url($post->post_name) to redirect to the post with an url with post_name : https://my_website.com/my_page

2. redirect the page to it's version without post_id

additionally, on the post i use the template_redirect hook to check if the current uri match the post_name (after a bunch of tests to check if I'm on the right post), if not I redirect the page to the url with post_name :

function check_url_for_post_id() {
  if (!is_my_post()) {
    return;
  }

  $post_id = get_the_ID();
  $current_post = get_post($post_id);
  if (is_null($current_post)) {
    return;
  }
  $current_slug = trim($_SERVER['REQUEST_URI'], '/');
  $slug = trim($current_post->post_name, '/');

  if ($slug !== $current_slug) {
    wp_safe_redirect(home_url($slug));
    exit;
  }
}
add_action('template_redirect', 'check_url_for_post_id');

So i'm using $_SERVER and I don't know if it's safe ? on this question, some people said we should not use $_GET and $_POST, and I suppose also not $_REQUEST or $_SERVER because they are vulnerable to attacks : https://stackoverflow.com/questions/13652605/extracting-a-parameter-from-a-url-in-wordpress

anyway, I suppose that in my case it's ok, since I only use it for comparison, I don't use it's content otherwise

本文标签: permalinkshow to ensure url uses postname and not query post id