「プリティリンク」はよくリクエストされるトピックですが、完全に説明されることはめったにありません。 mod_rewriteは「きれいなリンク」を作成する方法の1つですが、複雑で構文が非常に簡潔でわかりにくいため、ドキュメントではHTTPのある程度の習熟度を前提としています。誰かが「きれいなリンク」の仕組みとmod_rewriteを使用してそれらを作成する方法を簡単な用語で説明できますか?
他の一般名、エイリアス、クリーンURLの用語:RESTful URL、ユーザーフレンドリーURL、SEOフレンドリーURL、スラッギング、MVC URL(おそらく誤った名前)
Mod_rewriteが何を行うかを理解するには、最初にWebサーバーの動作を理解する必要があります。 Webサーバーは HTTPリクエスト に応答します。最も基本的なレベルのHTTPリクエストは次のようになります。
GET /foo/bar.html HTTP/1.1
これは、URL/foo/bar.html
を要求するWebサーバーへのブラウザーの単純な要求です。 ファイルを要求せず、任意のURLのみを要求することを強調することが重要です。リクエストは次のようにもなります。
GET /foo/bar?baz=42 HTTP/1.1
これはURLのリクエストと同じくらい有効であり、ファイルとはまったく関係ありません。
Webサーバーは、ポートでリッスンし、そのポートから着信するHTTP要求を受け入れて応答を返すアプリケーションです。 Webサーバーは、適切と思われる方法で、または応答するように構成した方法で、要求に自由に応答できます。この応答はファイルではなく、HTTP応答であり、ディスク上の物理ファイルと関係がある場合とない場合があります。 WebサーバーはApacheである必要はありません。他の多くのWebサーバーはすべて、持続的に実行され、HTTP要求に応答するポートに接続されている単なるプログラムです。自分で作成できます。この段落は、URLがファイルに直接等しいという概念からあなたを引き離すことを意図していました。これは理解することが本当に重要です。 :)
ほとんどのWebサーバーのデフォルト設定では、ハードディスク上のURLと一致するファイルを検索します。サーバーのdocument rootが例えば/var/www
に設定されている場合、ファイル/var/www/foo/bar.html
が存在するかどうかを調べ、存在する場合はそれを提供します。ファイルが「.php」で終わる場合、PHPインタープリターが呼び出され、thenが結果を返します。この関連付けはすべて完全に構成可能です。 WebサーバーがPHPインタープリターを介して実行するために、ファイルの末尾が「.php」である必要はなく、ディスク上の特定のファイルと一致させる必要はありません。
mod_rewriteは、内部リクエスト処理をrewriteする方法です。 WebサーバーがURL /foo/bar
のリクエストを受信すると、Webサーバーがディスク上のファイルを検索する前に、そのURLを他の何かにrewriteできますそれに一致します。簡単な例:
RewriteEngine On
RewriteRule /foo/bar /foo/baz
このルールは、リクエストが「/ foo/bar」に一致するたびに、「/ foo/baz」に書き換えます。リクエストは、あたかも処理されます代わりに/foo/baz
が要求されていました。これは、たとえば次のようなさまざまな効果に使用できます。
RewriteRule (.*) $1.html
このルールは、すべて(.*
)およびcapturesに一致し((..)
)、その後「.html」を追加するように書き換えます。つまり、/foo/bar
が要求されたURLであった場合、/foo/bar.html
が要求されたものとして処理されます。正規表現のマッチング、キャプチャ、および置換の詳細については、 http://regular-expressions.info を参照してください。
別のよくあるルールは次のとおりです。
RewriteRule (.*) index.php?url=$1
これもまた、あらゆるものに一致し、最初に要求されたURLをurl
クエリパラメーターに追加して、index.phpファイルに書き換えます。つまり、着信するすべてのリクエストに対して、ファイルindex.phpが実行され、このファイルは$_GET['url']
の元のリクエストにアクセスできるため、必要なことは何でもできます。
主に、これらの書き換えルールをWebサーバー構成ファイルに配置します。また、Apacheでは、ドキュメントルート内の.htaccess
というファイル(つまり、.phpファイルの隣)にそれらを配置することもできます。
*IfプライマリApache設定ファイルで許可;オプションですが、多くの場合有効になっています。
mod_rewriteは、すべてのURLを魔法のように「きれい」にするわけではありません。これはよくある誤解です。 Webサイトにこのリンクがある場合:
<a href="/my/ugly/link.php?is=not&very=pretty">
mod_rewriteがそれをきれいにするためにできることは何もありません。これをきれいなリンクにするには、次のことをする必要があります。
リンクをきれいなリンクに変更します。
<a href="/my/pretty/link">
サーバーでmod_rewriteを使用して、上記の方法のいずれかを使用して、URL /my/pretty/link
への要求を処理します。
( mod_substitute
を使用して、発信HTMLページとそれに含まれるリンクを変換できます。これは通常、HTMLリソースを更新するよりも手間がかかります。)
Mod_rewriteには多くのことができ、いくつかの書き換えのチェーン、完全に異なるサービスまたはマシンへのリクエストのプロキシ、特定のHTTPステータスコードの応答としてのリクエスト、リクエストのリダイレクトなど、作成できる非常に複雑なマッチングルールがあります。基本的なHTTP要求/応答メカニズムを理解している場合、非常に役立ちます。 notは自動的にリンクをきれいにします。
可能なすべてのフラグとオプションについては、 公式ドキュメント を参照してください。
decezeの答え を拡張するために、いくつかの他のmod_rewrite機能の例と説明を提供したいと思いました。
以下の例はすべて、RewriteEngine On
ファイルに.htaccess
がすでに含まれていることを前提としています。
この例を見てみましょう:
RewriteRule ^blog/([0-9]+)/([A-Za-z0-9-\+]+)/?$ /blog/index.php?id=$1&title=$2 [NC,L,QSA]
ルールは4つのセクションに分かれています。
RewriteRule
-書き換えルールを開始します^blog/([0-9]+)/([A-Za-z0-9-\+]+)/?$
-これはパターンと呼ばれますが、ルールの左側と呼ぶことにします-書き直したいものblog/index.php?id=$1&title=$2
-置換と呼ばれる、または書き換えルールの右側-書き換え先[NC,L,QSA]
は書き換えルールのフラグで、コンマで区切られます。これについては後で詳しく説明します上記の書き換えにより、/blog/1/foo/
のようなものにリンクでき、実際に/blog/index.php?id=1&title=foo
をロードします。
^
はページ名の開始を示します。したがって、example.com/blog/...
は書き換えられますが、example.com/foo/blog/...
は書き換えられません。(…)
括弧の各セットは、ルールの右側で変数としてキャプチャできる正規表現を表します。この例では:([0-9]+)
-は、長さが1文字以上で、数値(0-9)のみの文字列に一致します。これは、ルールの右側の$1
で参照できます-
または+
(+
のみ)を含む、長さが1文字以上の文字列に一致しますこれは、エスケープせずに 正規表現の繰り返し文字 )として実行されるため、バックスラッシュでエスケープされます。これは、ルールの右側の$2
で参照できます?
は、先行する文字がオプションであることを意味するため、この場合は/blog/1/foo/
と/blog/1/foo
の両方が同じ場所に書き換えられます$
は、これが一致する文字列の終わりであることを示しますこれらは、特定の条件を指定するために、書き換えルールの最後に角かっこで追加されたオプションです。繰り返しますが、 ドキュメント で読むことができる多くの異なるフラグがありますが、私はいくつかのより一般的なフラグを見ていきます:
NC
No caseフラグは、書き換えルールが大文字と小文字を区別しないことを意味します。したがって、上記の例のルールでは、これは/blog/1/foo/
と/BLOG/1/foo/
(またはこのバリエーション)の両方が一致することを意味します。
L
最後のフラグは、これが処理されるべき最後のルールであることを示します。これは、このルールが一致する場合にのみ、現在の書き換え処理の実行でそれ以上のルールが評価されないことを意味します。ルールが一致しない場合、他のすべてのルールは通常どおり順番に試行されます。 L
フラグを設定しない場合、以下のすべてのルールがrewrittenURLに適用されます。
END
Apache 2.4以降では、[END]
フラグも使用できます。それに一致するルールは、completelyさらにエイリアス/書き換え処理を終了します。 (一方、[L]
フラグは、たとえばサブディレクトリへの書き込みやサブディレクトリからの書き換えの場合など、2回目のラウンドをトリガーすることがよくあります。)
QSA
クエリ文字列追加フラグを使用すると、指定されたURLに追加の変数を渡して、元のgetパラメーターに追加できます。この例では、これは/blog/1/foo/?comments=15
のようなものが/blog/index.php?id=1&title=foo&comments=15
をロードすることを意味します
R
このフラグは、上記の例で使用したものではありませんが、言及する価値があると考えたものです。これにより、ステータスコード(例:R=301
)を含めるオプションを使用して、httpリダイレクトを指定できます。たとえば、/ myblog /から/ blog /への301リダイレクトを実行する場合は、次のようなルールを記述します。
RewriteRule ^/myblog/(*.)$ /blog/$1 [R=301,QSA,L]
書き換え条件 書き換えをさらに強力にし、より具体的な状況に合わせて書き換えを指定できるようにします。 ドキュメント で読むことができる多くの条件がありますが、いくつかの一般的な例に触れて説明します:
# if the Host doesn't start with www. then add it and redirect
RewriteCond %{HTTP_Host} !^www\.
RewriteRule ^ http://www.%{HTTP_Host}%{REQUEST_URI} [L,R=301]
これは非常に一般的な方法で、ドメインにwww.
が追加され(まだない場合)、301リダイレクトが実行されます。たとえば、http://example.com/blog/
をロードすると、http://www.example.com/blog/
にリダイレクトされます
# if it cant find the image, try find the image on another domain
RewriteCond %{REQUEST_URI} \.(jpg|jpeg|gif|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*)$ http://www.example.com/$1 [L]
これは少し一般的ではありませんが、ファイル名がサーバー上に存在するディレクトリまたはファイルである場合に実行されないルールの良い例です。
%{REQUEST_URI} \.(jpg|jpeg|gif|png)$ [NC]
は、jpg、jpeg、gif、またはpng(大文字と小文字を区別しない)のファイル拡張子を持つファイルに対してのみ書き換えを実行します。%{REQUEST_FILENAME} !-f
は、ファイルが現在のサーバーに存在するかどうかを確認し、存在しない場合にのみ書き換えを実行します%{REQUEST_FILENAME} !-d
は、ファイルが現在のサーバーに存在するかどうかを確認し、存在しない場合にのみ書き換えを実行しますRewriteRulesを使用せずに、多くの基本的な仮想URLスキームを実現できます。 Apacheでは、PHPスクリプトを.php
拡張なしで、また仮想PATH_INFO
引数を使用して呼び出すことができます。
最近では、デフォルトで AcceptPathInfo On
が有効になっています。基本的に、.php
およびその他のリソースURLが仮想引数を保持できます。
http://example.com/script.php/virtual/path
これで、この/virtual/path
はPHPに $_SERVER["PATH_INFO"]
として表示されます。ここで、任意の追加引数を処理できます。
これは、Apacheが$1
、$2
、$3
に別々の入力パスセグメントを持ち、それらを別個の$_GET
変数としてPHPに渡すほど便利ではありません。それは、より少ない設定労力で「きれいなURL」をエミュレートするだけです。
.php
拡張機能を非表示にしますURLで.php
「ファイル拡張子」を回避する最も簡単なオプションは、次を有効にすることです。
Options +MultiViews
これにより、Apacheは、ベース名が一致するため、article.php
のHTTPリクエストに/article
を選択します。そして、これは前述のPATH_INFO機能とうまく機能します。したがって、http://example.com/article/virtual/title
のようなURLを使用できます。複数のPHP呼び出しポイント/スクリプトを持つ従来のWebアプリケーションがある場合、これは理にかなっています。
ただし、MultiViewsにはさまざまな目的があります。 Apacheは常に一致するベース名を持つ他のファイルを探すため、非常にマイナーなパフォーマンスの低下を招きます。実際には Content-Negotiation を対象としているため、ブラウザは利用可能なリソース(article.en.php
、article.fr.php
、article.jp.mp4
など)の中から最適な選択肢を受け取ります。
.php
スクリプトのSetTypeまたはSetHandlerURLで.php
接尾辞を持ち歩くことを避けるためのより指示されたアプローチは、 PHPハンドラーの設定 他のファイルスキーム用です。最も簡単なオプションは、.htaccess
を介してデフォルトのMIME/handlerタイプをオーバーライドすることです。
DefaultType application/x-httpd-php
この方法では、article.php
スクリプトの名前をarticle
(拡張子なし)に変更するだけで、PHPスクリプトとして処理できます。
これで、すべての拡張機能のないファイルがPHPを介してパイプされるため、セキュリティとパフォーマンスに影響を与える可能性があります。したがって、代わりに、個々のファイルに対してのみこの動作を設定できます。
<Files article>
SetHandler application/x-httpd-php
# or SetType
</Files>
これは、サーバーのセットアップと使用されるPHP SAPIに多少依存します。一般的な代替には、ForceType application/x-httpd-php
またはAddHandler php5-script
が含まれます。
繰り返しますが、このような設定は1つの
.htaccess
からサブフォルダーに伝播することに注意してください。静的リソース、およびupload /ディレクトリなどのスクリプトの実行(SetHandler None
およびOptions -Exec
またはphp_flag engine off
など)は常に無効にする必要があります。
その多くのオプションの中で、Apacheはmod_alias
機能を提供します-これは時々mod_rewrite
s RewriteRulesと同じように機能します。ただし、これらのほとんどは、ディレクトリごとの<VirtualHost>
構成ファイルではなく、.htaccess
セクションで設定する必要があります。
ScriptAliasMatch
は主にCGIスクリプト用ですが、PHPでも機能するはずです。 RewriteRule
と同様に正規表現を使用できます。実際、これはおそらくキャッチオールフロントコントローラーを構成する最も堅牢なオプションです。
そして、単純な Alias
は、いくつかの簡単な書き換えスキームにも役立ちます。
単純な ErrorDocument
ディレクティブでも、PHPスクリプトに仮想パスを処理させることができます。ただし、これは厄介な回避策であり、GETリクエスト以外は禁止し、定義によりerror.logをフラッディングすることに注意してください。
詳細なヒントについては、 http://httpd.Apache.org/docs/2.2/urlmapping.html を参照してください。