2

次の書き換え規則があります。

 RewriteRule ^([A-Za-z0-9\_]+)$ index.php?rewrite=$1 [L,QSA]

?rewrite=$1 を、リクエスト uri のクエリ文字列を介して渡されるものよりも優先させる方法があるかどうか疑問に思っていました。

現在のところ、次の URL がヒットした場合、QSA フラグ(これは必要です) によります。

 http://www.domain.com/this_rewrite_will_match_the_above_rule?rewrite=some_value

PHP の $_GET['rewrite'] の値は、this_rewrite_will_match_the_above ruleではなく、some_valueになります。

書き換えを変更し、クエリ文字列に一致するように RewriteCond を追加する前に、ターゲット URL (この場合は index.php?rewrite=$1) を設定するフラグがあることを望んでいました。渡されたクエリ文字列値よりも優先されます。

これが理にかなっていることを願っています。

ありがとう。

4

4 に答える 4

2

少しハック

RewriteRule ^([A-Za-z0-9\_]+)$ index.php?%{QUERY_STRING}&rewrite=$1 [L]

これが機能するのは、php では 2 番目rewrite=...が最初のものを上書きするためです。

于 2012-12-09T21:05:58.020 に答える
2

JpsyとGerbenが提供する例よりも少しきれいなので、私は自分の答えを作成することを選択しました。

クレジットは当然のことですが、彼らの提案は私をここに導いたものです。私はそれらを拡張しただけです:

したがって、最終的なソリューションには 2 つのルールが含まれます。

# check if querystring is not empty (this is the addition vs other answers)
RewriteCond %{QUERY_STRING} !^$
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([A-Za-z0-9\_]+)$ index.php?%{QUERY_STRING}&rewrite=$1 [L]

上記のクエリ文字列が失敗した場合 (主にクエリ文字列が空である場合)、このルールが適用されます。

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([A-Za-z0-9\_]+)$ index.php?rewrite=$1 [L]

このデュアル ルールのセットアップを選択した理由は、クエリ文字列が空の場合に、php サーバー変数が "?&rewrite=...." で汚染されるのを避けるためです。

助けてくれた jpsy と gerben に感謝します。

于 2012-12-10T17:03:10.783 に答える
2

Apacheの書き換えで単一のクエリ文字列パラメーターをオーバーライドするメカニズムを複数回、非常に熱心に検索しましたが、最新のApacheバージョン(この記事の執筆時点では2.4.3)であっても、それを行うオプションはないようです。 .

しかし、PHP クエリ文字列パーサーが複数の同一のクエリ文字列パラメーターの最後のみを返すという事実を利用する代替手段があります。

例:

http://www.domain.com/index.php?id=123&id=456

これにより、$_GET に次の単一 (!) エントリが返されます。

array(1) {
  ["id"]=>
  string(3) "456"
}

そのため、オーバーライド パラメーターを既存のクエリ文字列の末尾に追加するだけで問題を解決できます(クエリ文字列内でそれらを削除する必要はありません)。繰り返されるパラメータの最後のオカレンスは、$_GET 配列になります。

残念ながら、QSA スイッチは常に元のパラメーターを新しいクエリ文字列の末尾に追加するため、この手法には適していません。古いパラメータを前置するスイッチはありません。そのため、QSA を使用する代わりに、RewriteCond で少し迂回して、元のクエリ文字列を自分でキャッチして先頭に追加する必要があります。

RewriteCond  %{QUERY_STRING}  ^(.*)$
RewriteRule ^([A-Za-z0-9\_]+)$ index.php?%1&rewrite=$1 [L]

RewriteCond の唯一の機能は、クエリ文字列を %1 にキャプチャすることです。条件の正規表現(.*)は常に一致するため、次の RewriteRule は常に実行されます。

この手法を使用すると、上記のテストケースは次のように書き換えられます...

http://www.domain.com/index.php?rewrite=some_value&rewrite=this_rewrite_will_match_the_above_rule

...これは、PHP クエリ文字列パーサーによって次のように解釈されます。

$_GET["id"] => "this_rewrite_will_match_the_above_rule"

...それはあなたが望むものです。

これは、クエリ文字列の値を PHP の $_GET 配列から取得する場合にのみ機能することに注意してください。$_SERVER["QUERY_STRING"]自分のコンテンツを解析したり、他のプログラミング言語を使用したりすると、必ずしも機能するとは限りません。

于 2012-12-09T21:26:57.530 に答える
0

次の手順を使用しました。

RewriteRule ([^\?]*)\?(.*) $1?$2 [N]                          (1)
RewriteCond %{QUERY_STRING} (.*?)&?(rewrite=[^&]+)&?(.*)      
RewriteRule ^(.*)$ $1?%1&%3 [N]                               (2)
RewriteRule ^(.*)$ $1?domain=newValue [L,QSA]                 (3)

このトリックは、最初の 2 つのルールの [N] フラグによって行われます。これにより、エンジンが書き換えられ、出力が再処理されます。

ルール(1) シンプルにURLをそのまま書き換えます。mod_proxy_ajp と一緒に mod_rewrite を使用していて、最初の反復でクエリ文字列が URL から分割されていないため、必要でした。最初の行の実行後、URL は変更されませんが、エンジンはクエリ文字列からパスを分割します。

ルール (2) は、クエリ文字列からパラメーター「rewrite」のすべての出現を反復して削除します。

ルール (3) は、パラメーターの新しい値を設定し、ルール (2) によって行われた置換から生き残ったクエリ文字列を追加します。

于 2014-08-14T08:28:18.227 に答える