Strange behaviour - too many parameters?

Oh, the strange things mod_rewrite does!

Strange behaviour - too many parameters?

Postby moviemaniac » Mon Aug 06, 2007 3:18 am

Hi

this is my first post :D

I am running Apache/2.2.3 (Linux/SUSE) with mod_rewrite, and I am experiencing some issues with my rewrite rules.

I've the following url

Code: Select all
http://127.0.0.1/monitor/index.php?mod=programs&opt=dtls&pid=446&filter=0&ctx=user&p=3#user


which I rewrite with php and send to the browser in this way:

Code: Select all
http://127.0.0.1/monitor/programs-opt-dtls-pid-446-filter-0-ctx-user-p-3.html#user


in my .htaccess I've the following rewriting rule:

Code: Select all
RewriteEngine On
RewriteBase /monitor/

RewriteRule ^([^-]+)-([^-]+)-([^-]+)-([^-]+)-([^-]+)-([^-]+)-([^-]+)-([^-]+)-([^-]+)-([^-]+)-([^-]+)\.html$ index.php?mod=$1&$2=$3&$4=$5&$6=$7&$8=$9&$10=$11 [L,QSA,NS,NC]


The fact is that it seems that mod_rewrite is having some problems in interpreting this rule the right way.
Everything works well up to parameter $9.
Parameter $10 and $11 are not being recognized, and mod_rewrite is rewriting them simply appending 0 and 1 to parameter $1.

I hope I've been clear enough. Hope that someone can help :D

Thanks
moviemaniac
 
Posts: 4
Joined: Mon Aug 06, 2007 3:05 am

Postby richardk » Mon Aug 06, 2007 8:31 am

You can't have more then 9 because mod_rewrite can't tell if you wanted $10 or $1 and an 0.
http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html#rewriterule wrote:Back-references are identifiers of the form $N (N=0..9), which will be replaced by the contents of the Nth group of the matched Pattern.


You could use a RewriteCond as well (this would limit you to 18)
Code: Select all
Options +FollowSymLinks

RewriteEngine On

# This matches the last two.
RewriteCond %{REQUEST_URI} -([^-]+)-([^-]+)\.html$ [NC]
# This matches the first 9.
RewriteRule ^([^-]+)-([^-]+)-([^-]+)-([^-]+)-([^-]+)-([^-]+)-([^-]+)-([^-]+)-([^-]+)-[^-]+-[^-]+\.html$ index.php?mod=$1&$2=$3&$4=$5&$6=$7&$8=$9&%1=%2 [NS,NC,QSA,L]


Or you could use PHP
Code: Select all
Options +FollowSymLinks

RewriteEngine On

RewriteRule ^([^-]+)-(([^-]+-){9}[^-]+)\.html$ index.php?mod=$1&*mr=$2 [NS,NC,QSA,L]

and at the top of index.php
Code: Select all
if(isset($_GET['*mr']) && !empty($_GET['*mr']))
{
  // Get rid of extra dashes at the beginning/end.
  $_GET['*mr'] = trim($_GET['*mr'], '-');
  // Split the string at the dashes.
  $_GET['*mr'] = explode('-', $_GET['*mr']);
  // If there's an odd number, add a null to the end of the
  // array to make it even so it doesn't error in the loop.
  if((count($_GET['*mr']) % 2) !== 0)
  {
    $_GET['*mr'][] = null;
  }
  // Loop through the array, two ata time adding to the GET array.
  for($i = 0; $i <= (count($_GET['*mr']) - 2); $i = $i +2)
  {
    $_GET[$_GET['*mr'][$i]] = $_GET['*mr'][$i+1];
  }
  unset($_GET['*mr']);
}


Edit: To fix a mistake in the PHP.
Last edited by richardk on Mon Aug 06, 2007 9:12 am, edited 1 time in total.
richardk
 
Posts: 8800
Joined: Wed Dec 21, 2005 7:50 am

Postby moviemaniac » Mon Aug 06, 2007 9:10 am

I think I'll go with the first one, because it looks cleaner :D
Most of all 18 parameters would be enough :D

The only thing is:
using your first example, I have to rewrite my urls before sending them to the browser togheter with the html code in a different way, right?

I mean, I am currently using rule like this:

Code: Select all
$search = $prefix . 'index.php\?mod=([\w\d\.\:\_\/]+)&(?:amp;)?([\w\d\.\:\_\/]+)=([\w\d\.\:\_\/]+)&(?:amp;)?([\w\d\.\:\_\/]+)=([\w\d\.\:\_\/]+)&(?:amp;)?([\w\d\.\:\_\/]+)=([\w\d\.\:\_\/]+)&(?:amp;)?([\w\d\.\:\_\/]+)=([\w\d\.\:\_\/]+)&(?:amp;)?([\w\d\.\:\_\/]+)=([\w\d\.\:\_\/]+)\#([\w\d\.\:\_\/]+)"|';

$replace = '"$1-$2-$3-$4-$5-$6-$7-$8-$9-$10-$11.'.$autourlsext.'#$12"';

$display = preg_replace($search, $replace, $display);


Could you please give me another hint?
Thanks :D
moviemaniac
 
Posts: 4
Joined: Mon Aug 06, 2007 3:05 am

Postby richardk » Mon Aug 06, 2007 9:19 am

I have to rewrite my urls before sending them to the browser togheter with the html code in a different way, right?

Yes, the same as with any rewrite like this.

I mean, I am currently using rule like this:

To do what? You should be changing how the links are actually created.

Could you please give me another hint?

About what?
richardk
 
Posts: 8800
Joined: Wed Dec 21, 2005 7:50 am

Postby moviemaniac » Mon Aug 06, 2007 9:37 am

ok, I'll try to be clearer.

You gave me two ways of doing things.
I've choosen the first one.
But looking at your code, the last two parameters are in the form %param and not $param.

Actually, I first rewrite all the urls that are in each page before sending the page to the browser.
Then I use a .htaccess file to let apache understand how to interpret the urls.

What I was asking is: using your method for urls with more than $9 parameters, do I have to rewrite those urls in a different way in php?
moviemaniac
 
Posts: 4
Joined: Mon Aug 06, 2007 3:05 am

Postby richardk » Mon Aug 06, 2007 9:52 am

What I was asking is: using your method for urls with more than $9 parameters, do I have to rewrite those urls in a different way in php?

No, you shouldn't have to do anything different. Have you tried? Some related information:
http://php.net/preg_replace wrote:replacement may contain references of the form \\n or (since PHP 4.0.4) $n, with the latter form being the preferred one. Every such reference will be replaced by the text captured by the n'th parenthesized pattern. n can be from 0 to 99, and \\0 or $0 refers to the text matched by the whole pattern. Opening parentheses are counted from left to right (starting from 1) to obtain the number of the capturing subpattern.

When working with a replacement pattern where a backreference is immediately followed by another number (i.e.: placing a literal number immediately after a matched pattern), you cannot use the familiar \\1 notation for your backreference. \\11, for example, would confuse preg_replace() since it does not know whether you want the \\1 backreference followed by a literal 1, or the \\11 backreference followed by nothing. In this case the solution is to use \${1}1. This creates an isolated $1 backreference, leaving the 1 as a literal.
richardk
 
Posts: 8800
Joined: Wed Dec 21, 2005 7:50 am

Postby moviemaniac » Mon Aug 06, 2007 1:11 pm

richardk wrote:
What I was asking is: using your method for urls with more than $9 parameters, do I have to rewrite those urls in a different way in php?

No, you shouldn't have to do anything different. Have you tried?


Now I've tried and it works like a charm :D
Thanks a lot, you've been of great help.

Sincerely, Enrico
moviemaniac
 
Posts: 4
Joined: Mon Aug 06, 2007 3:05 am


Return to Idiosyncrasies

Who is online

Users browsing this forum: No registered users and 2 guests

cron