i make migration plugin from specific script to wordpress, but i have a problem on redirect old urls to new one

old urls is like book.php?view=12a34b56 and i want redirect it to book/12a34b56

i try to make it by add_rewrite_rule like this

init function >

but rewrite rule not detect query args i don't know why, so i'm changed the method to

query_vars function >
        array_push($vars, 'view');

pre_get_posts function >
        if (!is_admin() && is_main_query() && get_query_var('pagename') === 'book.php' && get_query_var('view') != '') {
            $query->set('name', get_query_var('view'));

            // after redirect to new url, view arg not removed
            // new url be like this book/12a34b56/?view=12a34b56
            // i try to remove view arg in url after set query but it's still not removed
            $query->set('view', false);
            set_query_var('view', false);

this method work perefectly but i still have one problem like i say in code comments new url be like book/12a34b56/?view=12a34b56, how i can remove ?view=12a34b56 after set post name, or method to detect query args on add_rewrite_rule that will be great.

NOTE : i do not want edit .htaccess directly

1 Answer 1


It doesn't work with add_rewrite_rule() because of the ?view= part in the URL (it's the first parameter for the function) — i.e. WordPress strips that query string part, hence it's not included when WordPress finds a matching rewrite rule.

how I can remove ?view=12a34b56 after set post name

You can't (not on the same page), because that is a query string in the request URL which PHP reads from upon loading the page, and the browser already "put" the URL in the address bar.

But because I believe you want a 301 (permanent) redirect whereby the URL in the browser's address bar changes, then you can easily achieve that redirect via the parse_request hook — you could also use the init hook, but with parse_request, WordPress already parses the request path (e.g. https://example.com/this-path/), so we can simply read from the parsed data, i.e. the $wp->request below.

So this should work for you, but make sure to remove that pre_get_posts code from your file:

add_action( 'parse_request', 'wpse_375940' );
function wpse_375940( $wp ) {
    if ( 'book.php' === $wp->request &&
        ! empty( $_GET['view'] )
    ) {
        $query = new WP_Query( [
            'name'   => $_GET['view'],
            'fields' => 'ids',
        ] );

        if ( ! empty( $query->posts ) &&
            $url = get_permalink( $query->posts[0] )
        ) {
            // Or use 302. It's up to you to decide.
            wp_redirect( $url, 301 );
  • 1
    thank you, it's work, have a nice day
    – Boyzen
    Commented Oct 5, 2020 at 4:13

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.