WordPress - Rewrite rules with multiple parameters - regex

I'm setting up a WordPress page that would normally accept two querystring parameters. Our host prefers the use of rewrite rules instead of querystrings, so I have to take that approach.
So where I'd normally do this:
domain.com/animal-page.php?animal=dog&color=brown
I have to do this:
domain.com/animal-page/animal/dog/color/brown
The problem I am running into is that the second querystring parameter is optional.
A rewrite rule like this wouldn't work:
add_rewrite_rule(
'([\-\w+]*)/animal/([\w+]*)/color/([\w+]*)',
'index.php?pagename=$matches[1]&animal=$matches[2]&color=$matches[3]',
'top'
);
...because if the color parameter is left off the URL (which is a possibility), that Regex fails.
I've also tried making query param (color) and value (brown) optional in the Regex, and it still doesn't work:
add_rewrite_rule(
'([\-\w+]*)/animal/([\w+]*)(\/color\/?)([\w+]*)',
'index.php?pagename=$matches[1]animal=$matches[2]&$matches[3]=$matches[4]',
'top'
)
My question is: Is there a way to make the second query parameter optional? I want the page to react appropriately if the 'color' parameter is left off the URL.
Thanks,

In this case you will need to make two separate rules:
add_rewrite_rule(
'([\-\w+]*)/animal/([\w+]*)/?$',
'index.php?pagename=$matches[1]&animal=$matches[2]',
'top'
);
and
add_rewrite_rule(
'([\-\w+]*)/animal/([\w+]*)/color/([\w+]*)',
'index.php?pagename=$matches[1]&animal=$matches[2]&color=$matches[3]',
'top'
);

Related

Rewrite rule accepting #

I have the current RewriteRule:
RewriteRule ^search/([0-9a-zA-Z-\s-:]+)(/?)$ search.php?search=$1 [NC,L,NE]
I'm wanting to have an url like this /search/#ff2266/, to accept hex (with the #) colors in the url and then have this value in the $_GET['search'] variable. But not only this, but I'm having problem with the #.
Is there any way i could do something like this: ([#0-9a-zA-Z-\s-:]+) ?
I've tried the rule:
RewriteRule ^search/(.*)(/?)$ search.php?search=$1 [NC,L,NE]
And then in the search.php the following code:
echo "var_dump($_GET): ";
var_dump($_GET);
and with the url /search/#f44336/ the result is:
var_dump(Array): array(0) { }
See, the part of a URI after the # is called "fragment" and is by definition only available/processed on client side (see https://en.wikipedia.org/wiki/Fragment_identifier).
On the client side, this can be accessed using javaScript with window.location.hash.
If you want to access that number in your search file, you could pass it to there without the hash char and use it that way.

fastcgi_cache_key exclude some args in request uri

My fastcgi_cache_key is:
fastcgi_cache_key "$host$request_method$request_uri";
My $request_uri has timestamp and signature in it:
/abc/xyz?product_id=10529125896&shop_id=17224077&shop=abc.com&path_prefix=%2Fa%2Fcomment&timestamp=1503044416&signature=882102c51c7b7bd4c5d8521a6565fc70c27b908547316f1123eb4af13b19f2da
So, the cache always MISS (because it has different timestamp and signature). My question is:
I want to create new var and use that var for fastcgi_cache_key. That var will has something like this:
myvar
/abc/xyz?product_id=10529125896&shop_id=17224077&shop=abc.com
fastcgi_cache_key will like this:
fastcgi_cache_key "$host$request_method$myvar";
How can I do that ? Thanks so much.
There are two ways to do it.
if ($request_uri ~ "([^\?]*)\?(.*)timestamp=([^&]*)&?(.*)") {
set $args $2$4;
}
fastcgi_cache_key "$host$request_method$args";
This will remove the timestamp. You can either modify the pattern to ignore one more field or you can use it twice to remove the field from $args.
Next option is to use openresty or Nginx with lua which allows you to execute Lua script in your code. if conditions are not considered good. But then having lua increases your software requirement

Can you make WooCommerce shortcodes from template parts?

I'm interested in creating shortcodes that basically fill in template parts of the WooCommerce checkout. For example, in functions.php of my child theme:
function shortcode_review_order() {
//get the template part from woocommerce/templates/checkout/review-order.php
wc_get_template_part('checkout/review-order');
}
add_shortcode( 'custom_review_order', 'shortcode_review_order' );
...and then in my page...
<div>[custom_review_order]</div>
When I tried this, nothing appeared in my checkout page.
Is this even possible?
there are few things wrong in your code...
first, you should add a shortcode using the init hook.
add_action( 'init', 'add_shortcodes' );
function add_shortcodes(){
add_shortcode( 'custom_review_order', 'shortcode_review_order' );
}
then you lack the .php part of the template. Also it needs the array parameter like below. And you might get more accurate result using wc_get_template.
function shortcode_review_order(){
wc_get_template( 'checkout/review-order.php', array( 'checkout' => WC()->checkout() ) );
}
To know more on how to correctly use it's template, search for each on the plugin. You'll see how it's being used. And you can get a hint on how you can use it for yourself.
I found that wc_get_template echos out the template, instead, for shortcodes returning the template is better. You can use:
$string = wc_get_template_html( $template_name, $args, $template_path, $default_path );
It is "Like wc_get_template, but returns the HTML instead of outputting."
https://docs.woocommerce.com/wc-apidocs/function-wc_get_template_html.html

Ignore case in prettyfaces pattern

if you defined a url mapping as follows:
#URLMapping(id = "myPage", pattern = "/myPage", viewId = "/faces/pages/myPage.xhtml")
if you tried to enter the url as:
http:localhost:8080/myPage
this will work fine, but if you changed the case to:
http:localhost:8080/mypage
or http:localhost:8080/MYPAGE
it won't work, it won't find the page, so is there's a way to ignore the case in the pattern, or such thing is not supported in PrettyFaces yet, if not supported, then please suggest a workaround.
Something like this is currently not directly supported with PrettyFaces. But you could achieve something like this with a simple workaround:
Change your mapping to a completely lowercase URL:
#URLMapping(id = "myPage", pattern = "/mypage", viewId = "/faces/pages/myPage.xhtml")
And then add a rewrite rule that performs the lowercase transformation:
<rewrite match="(?i)/mypage" toCase="lowercase" redirect="chain" />
I think this should work fine. You could also try to build a more general pattern so that you don't have to repeat the rewrite rule for every mapping.

Can mod_rewrite convert any number of parameters with any names?

I'm a total n00b at mod_rewrite and what I'm trying to do sounds simple:
instead of having domain.com/script.php?a=1&b=2&c=3 I would like to have:
domain.com/script|a:1;b:2;c:3
The problem is that my script takes a large number of parameters in a variety of combinations, and order is unimportant, so coding each one in the expression and expecting a certain order is unfeasible. So can a rule be set up that simply passes all of the parameters to the script, regardless of order or how many parameters? So that if someone types
domain.com/script|a:1;b:2;j:7 it will pass all those params and values just the same as it would with domain.com/script|b:2;a:1; ?
Thanks!
I would use PHP to parse the requested URL path:
$_SERVER['REQUEST_URI_PATH'] = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$params = array();
foreach (explode(',', substr($_SERVER['REQUEST_URI_PATH'], 6)) as $param) {
if (preg_match('/^([^:]+):?(.*)$/', $param, $match)) {
$param[rawurldecode($match[1])] = rawurldecode($match[2]);
}
}
var_dump($params);
And the mod_rewrite rule to rewrite such requests to your /script.php file:
RewriteRule ^script\|.+ script.php [L]