0

The url I am trying to rewrite looks like this.

root_domain/something/something-else/also-different-1030/?success=1289

With this rewrite rule I am trying to catch the url and direct it to the post with ID 1289.

function my_success_rewrite_rule() {
    add_rewrite_rule( '.+success=([0-9]+)$', 'index.php?p=$matches[1]', 'top' );    
}
add_action( 'init', 'my_success_rewrite_rule' );

Here is the regex I tested for the url.
https://regex101.com/r/nUENTl/1/

In the regex you can see that group 1 catches the post ID or $matches[1]. When I remove the ? from the url it works perfect and redirects any url with success=1289 at the end to the post with ID 1289.

However when I include the ? in the url it does not work, despite taking care of that in the regex by specifying . for any character and + as quanitfier for any number of occurrences and then success at the beginning of the regex before the capture group, the characters inside the ( ) followed by a $ to mark the end of the url string.

What does my rewrite rule need to look like to be able to keep the ? in the url and still rewrite the url to show post 1289 in this case? I am not sure how to escape or take care of the ?. Using .+\?success, so escaping the ? does not work.

I am also using Monkeyman Rewrite Analyzer and it shows me that the rewrite rule is being caught correctly.

enter image description here

I am also using flush_rewrite_rules( true ); in functions.php file to flush the rules each time I save, this to avoid having to manually update the permalinks settings page in the dashboard.

Also I am not adding a rewrite tag since p is a public query var, so no need to add that to WP since I want to get the post by ID, so I need to use p=$matches[1] (I think, pls correct me if this is wrong thinking, thx).

edit
To explain better why I think I need a ? in the url is this. The url is what the user is redirected to upon clicking a verification link. I could of course also omit the ? from the url the user is redirected to but I am not sure if that then is ok or the correct way of doing this.

if ( $verify === $verification ) {
    update_post_meta( $form_id, 'verification_id', 'verified', $verify );
    wp_safe_redirect( $url . '?success=' . $form_id );
}

So when the verification code is fine I update the post meta, then I take the original url the user was on when doing the verification and add the ?success=$form_id. I thought for WP to handle this fine and for me to also be able to use $_GET['success'] I have to have the ? in the url.

For example later on I am doing this to output information from the post I want.

function catch_success() {
    var_export( $_GET );
    if ( isset( $_GET['success'] ) ) {
        $post_id = $_GET['success'];
        $post = get_post( $post_id );
        var_export( $post );
        $user_reserved_seats = get_post_meta( $post_id, 'user_reserved_seats', true );
        var_export( $user_reserved_seats );
    }
}
add_action( 'template_redirect', 'catch_success' );

And initially I thought, to be able to use the catch_success function I need to have a ? in the url.

But instead of doing all that I should just omit the ? and redirect to the post I want to right after the verification link checks out?

Because as it stands now I think I have 2 redirects, 1 from the verification link and then from there to the success link and 2 from the success link to the post in question, 1289. I should just redirect to the post in question directly form the verification link, yes? Or I could omit the ? and still have the /success=1289 link redirected with a rewrite rule, to post 1289?

Bit of history, I asked this recently and is has to do with this in the sense that this is a follow up or the next step.

  • 1
    I don't think the question mark is a part of the URL at all, that's a part of the get parameters. Even if you can match it with a regular expression, it won't be a part of the input that gets passed to the rewrite rules. This will never work with the question mark in the rewrite rule ( because that's not how URLs work ) – Tom J Nowell Oct 24 '18 at 18:42
  • @TomJNowell Very useful info, still working on understand it thoroughly. I added more info to why I think I need a ? in the url, but if you understand that all I am after is a success page with info about the item that got verified as a form response I might have to just make it simple and direct to the post without redirects. Not sure whether to have a always on static success page where users see their form submit success once and otherwise other info/public info, or if I have a one-time visible per user submit form success page with related user item data and a dynamic url. – lowtechsun Oct 24 '18 at 20:05
  • @TomJNowell and you are right, I found this The question mark is used as a separator, and is not part of the query string. here. Though now I am also a bit more confused, how then does rewriting work with a use case like this ? Meaning, how can/could example.com/?success=1234 then be translated to example.com/?p=1234 as there is a ? in the url. – lowtechsun Oct 24 '18 at 20:11
  • 1
    It isn't, because neither URL is a pretty permalink, neither would be matched by rewrite rules. The job of rewrite rules is to take /Im/a/foo/bar and turn it into something of the form /index.php?queryvar1=foo&queryvar2=bar etc, it's not a search replace. E.g. you can't rewrite on to a different PHP file, and you can't match GET parameters ( the whole point of permalinks is to hide them in the first place ). There is no hotfix kludge or hack that will make it match the ? or anything after it, that's not how URLs work – Tom J Nowell Oct 24 '18 at 20:15
  • 1
    As for how does it match things like /?p=123? It doesn't, there are no rewrite rules involved in GET parameters, and you can't match GET parameters – Tom J Nowell Oct 24 '18 at 20:19
2

The root problem here is a misunderstanding of how URLs work. What you see in the browser is not a full URL, but something to make it easier to understand

For example, take this URL:

http://example.com/test/?foo=bar#bananas

Here we have instructions to:

  • Via HTTP protocol aka http://
  • contact the server at example.com aka https://example.com
  • and do a GET HTTP request for /test/ aka https://example.com/test/
  • With the parameters foo=bar aka https://example.com/test/?foo=bar

WP Rewrite rules operate on the request, aka the /test/, so you can never match ?foo=bar part of a URL. The GET parameter foo gets put inside the $_GET array. Note how the # component is never sent, this part of the address is entirely client side.

So in order for your test to work, you will need to do two things:

  • Match on to the /something/something-else/also-different-1030/ part
  • Then check $_GET['success'] to see if it has a valid value

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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