How to prevent redirection to max 2147483647 for larger values of the page query variable?

The Why Part

If we have a page called technical and try to load:

example.tld/technical/99999999999999999999

then the 99999999999999999999 part is treated as a page query variable with the value of 2147483647.

The reason is this rewrite rule for pages:

rewrite rules

according to the handy Monkeyman Rewrite Analyzer by Jan Fabry.

This part of the WP_Query::get_posts():

if ( isset($q['page']) ) {
    $q['page'] = trim($q['page'], "https://wordpress.stackexchange.com/");
    $q['page'] = absint($q['page']);
}

is responsible for the integer conversion, i.e.

absint( '99999999999999999999' ) =  2147483647

This is actually the same as:

abs( intval( '99999999999999999999' ) )  

I tested also:

intval( 99999999999999999999 )

but that just gives 0.

I checked the PHP documentation on intval() that says:

The maximum value depends on the system. 32 bit systems have a maximum
signed integer range of -2147483648 to 2147483647. So for example on
such a system, intval(‘1000000000000’) will return 2147483647. The
maximum signed integer value for 64 bit systems is
9223372036854775807.

Strings will most likely return 0 although this depends on the
leftmost characters of the string. The common rules of integer casting
apply.

Finally the canonical redirect kicks in and redirects to:

example.tld/technical/2147483647/

Your current rewrite rule:

add_rewrite_rule(
    '^technical/([0-9])/?', 
    'technical/?pid=$matches[1]', 
    'bottom'
);

seems to be wrong. It’s e.g. missing the index.php part and only supports a single digit.

Workaround

Try e.g. (untested):

add_rewrite_rule(
    '^technical/([0-9]+)/?', 
    'index.php?pagename=technical&wpseid=$matches[1]', 
    'top' 
);

add_filter( 'query_vars', function( $qv )
{
    $qv[] = 'wpseid';
    return $qv;
} );

where I changed pid to wpseid to avoid possible name collisions.

Now you should be able to use $wpseid = get_query_var( 'wpseid' ); to retrieve it unmodified.

Note that you will most likely loose the possibility of content pagination for that page.

… or just switch to a 64 bit system where:

9223372036854775807 > 10101000003163

and just use a combination of is_page( 'technical' ) and get_query_var( 'page' ) but that sounds like be a messy solution, so I wouldn’t really recommend it 😉

Leave a Comment