.htaccessを使用したRewriteCondによるRewriteRuleのグループ化

Apr 16 2020

複数のランディングページを実行するために使用するWebページテンプレートがあり、htaccessを使用してPHPコード内のページIDにわかりやすいURLを送信します。それはすべて機能しますが、現時点では、すべてのルールまたはリダイレクトが衝突する前に、書き換え条件行を追加する必要があります。これは、以下の擬似コードで確認できます。

RewriteEngine On

RewriteCond for domain1
RewriteRule for page 1 on domain 1
RewriteCond for domain1
RewriteRule for page 2 on domain 1

RewriteCond for domain2
RewriteRule for page 1 on domain 2
RewriteCond for domain2
RewriteRule for page 2 on domain 2

これは適切に拡張できません。これを他の言語で実行している場合は、次のようなルールをグループ化します。

RewriteCond for domain1
{
    RewriteRule for page 1 on domain 1  
    RewriteRule for page 2 on domain 1
}

RewriteCond for domain2
{
    RewriteRule for page 1 on domain 2  
    RewriteRule for page 2 on domain 2
}

グループ化できれば、htaccessファイルの管理がはるかに容易になります。ルールをグループ化する方法はありますか?解決策を探してみましたが、出くわしたすべての例で、1つのドメインに対する1つのリダイレクトについて説明しています。私の他のアイデアは、PHP / MySQLでhtaccessスクリプトを作成し、データを入力してボタンを押すと、htaccessファイルが書き込まれることです。読み取るのは複雑ですが、問題ありません。簡単な解決策があると確信しています。誰か助けてもらえますか?

回答

1 PlatformDating Apr 17 2020 at 09:54

これが製品で機能している私の最終的な解決策です:

RewriteEngine On

<If "%{HTTP_HOST} == 'domain1.com'">        

        #main pages
        RewriteRule /members/$ /index.php?pageid=2 [NC,L] RewriteRule /contact/$    /index.php?pageid=3 [NC,L]
        RewriteRule /affiliates/$ /index.php?pageid=4 [NC,L] #blog articles RewriteRule /welcome-to-our-blog/$ /index.php?pageid=b0001 [NC,L]
</If>


<If "%{HTTP_HOST} == 'domain2.com'">        

        #main pages
        RewriteRule /about/$ /index.php?pageid=2 [NC,L] RewriteRule /press-kit/$    /index.php?pageid=3 [NC,L]
        RewriteRule /contact/$ /index.php?pageid=4 [NC,L] RewriteRule /affiliates/$   /index.php?pageid=5 [NC,L]

        #blog articles
        RewriteRule /welcome-to-our-blog/$ /index.php?pageid=b0001 [NC,L]
</If>
MrWhite Sep 22 2020 at 16:28

<If>セクションを使用する代わりのいくつかの方法は、警告がないわけではないためです。

  1. 条件が一致する(または一致しない)場合は、ディレクティブをスキップします
  2. URLの前に(一致させるために)ホスト名を付けます
  3. .htaccessホストごとに個別の構成ファイル

余談ですが、大文字と小文字を区別しない---NC一致が本当に必要ですか?)

1.条件が一致する(または一致しない)場合は、ディレクティブをスキップします

Sルール(または条件)が一致しない場合は、任意の数のディレクティブをスキップ(フラグ付け)できます。すなわち。あなたはときに従うルールをスキップした場合HTTP_HOSTでないdomain1.com場合は、以下のルールにのみ処理された後HTTP_HOSTですdomain1.com

例えば:

# Skip the following 4 rules when the host is not "domain1.com"
RewriteCond %{HTTP_HOST} !=domain1.com
RewriteRule ^ - [S=4]

# Only processed when the HTTP_HOST is equal to "domain1.com"

#main pages
RewriteRule ^members/$ /index.php?pageid=2 [NC,L] RewriteRule ^contact/$     /index.php?pageid=3 [NC,L]
RewriteRule ^affiliates/$ /index.php?pageid=4 [NC,L] #blog articles RewriteRule ^welcome-to-our-blog/$ /index.php?pageid=b0001 [NC,L]

# --------------------------------------------------------------------

# Skip the following 5 rules when the host is not "domain2.com"
RewriteCond %{HTTP_HOST} !=domain2.com
RewriteRule ^ - [S=5]

# Only processed when the HTTP_HOST is equal to "domain2.com"

#main pages
RewriteRule ^about/$ /index.php?pageid=2 [NC,L] RewriteRule ^press-kit/$   /index.php?pageid=3 [NC,L]
RewriteRule ^contact/$ /index.php?pageid=4 [NC,L] RewriteRule ^affiliates/$  /index.php?pageid=5 [NC,L]

#blog articles
RewriteRule ^welcome-to-our-blog/$ /index.php?pageid=b0001 [NC,L]

このアプローチの明らかな注意点は、S=<number>ルールを追加または削除するときにフラグを更新するように注意する必要があるということです。

明らかにロジックを逆にして、目次のように見えるものを上部に表示することができます。例えば:

RewriteCond %{HTTP_HOST} =domain1.com
RewriteRule ^ - [S=2]
RewriteCond %{HTTP_HOST} =domain2.com
RewriteRule ^ - [S=5]
RewriteCond %{HTTP_HOST} =domain3.com
RewriteRule ^ - [S=9]

# --------------------------------------------------------------------
# domain1.com

#main pages
RewriteRule ^members/$     /index.php?pageid=2 [NC,L]
RewriteRule ^contact/$ /index.php?pageid=3 [NC,L] RewriteRule ^affiliates/$  /index.php?pageid=4 [NC,L]

#blog articles
RewriteRule ^welcome-to-our-blog/$ /index.php?pageid=b0001 [NC,L] # -------------------------------------------------------------------- # domain2.com #main pages RewriteRule ^about/$       /index.php?pageid=2 [NC,L]
RewriteRule ^press-kit/$ /index.php?pageid=3 [NC,L] RewriteRule ^contact/$     /index.php?pageid=4 [NC,L]
RewriteRule ^affiliates/$ /index.php?pageid=5 [NC,L] #blog articles RewriteRule ^welcome-to-our-blog/$ /index.php?pageid=b0001 [NC,L]

「スキップ」ルールは、ルールを追加または削除するときに、これらのルールが該当する場所に応じていくつか更新する必要がある場合があるため、エラーが発生しやすい可能性があります。

2. URLの前に(一致させるために)ホスト名を付けます

または、(一時的に)URLパスの前にホスト名を付けて、以下のルールでこれと照合することもできます。これRewriteCondにより、後続のすべてのルールで追加のディレクティブが回避されます。

例えば:

# Prefix URL-path with HTTP_HOST if not already prefixed / No "L" flag
RewriteCond %{HTTP_HOST}@$1 !^([a-z.-]+)@\1 RewriteCond %{REQUEST_FILENAME} !-f RewriteRule (.*) %{HTTP_HOST}/$1

# --------------------------------------------------------------------
# domain1.com

#main pages
RewriteRule ^domain1\.com/members/$ /index.php?pageid=2 [NC,L] RewriteRule ^domain1\.com/contact/$     /index.php?pageid=3 [NC,L]
RewriteRule ^domain1\.com/affiliates/$ /index.php?pageid=4 [NC,L] #blog articles RewriteRule ^domain1\.com/welcome-to-our-blog/$ /index.php?pageid=b0001 [NC,L]

# --------------------------------------------------------------------
# domain2.com

#main pages
RewriteRule ^domain2\.com/about/$ /index.php?pageid=2 [NC,L] RewriteRule ^domain2\.com/press-kit/$   /index.php?pageid=3 [NC,L]
RewriteRule ^domain2\.com/contact/$ /index.php?pageid=4 [NC,L] RewriteRule ^domain2\.com/affiliates/$  /index.php?pageid=5 [NC,L]

#blog articles
RewriteRule ^domain2\.com/welcome-to-our-blog/$ /index.php?pageid=b0001 [NC,L]

これRewriteCondにより、追加のディレクティブが回避されますが、いずれの場合も、一致したURLパスの前にドメインを付ける必要があります。S上記の最初の例のようにフラグを使用する場合よりもエラーの可能性が低くなります。

上記の例では、ファイルに直接マップされていない、またはに書き換えられていないURLのリクエストの最後に、ホスト名がURLパスのプレフィックスとして残ります/index.php?pageid=<number>。これにより、404になります。

ホスト名プレフィックスを特に削除したい場合(おそらく$_SERVER['REDIRECT_URL']、ではなくエラードキュメントで変数を使用している場合$_SERVER['REQUEST_URI'])、追加の環境変数を導入して(それを呼び出しましょうFINISHED)、最後にこのプレフィックスを削除することでこれを行うことができます。

たとえば、最初のルールを変更してFINISHEDenv var(最初は存在しない)をチェックし、最後にプレフィックスを削除してenvvarを設定する新しいルールを導入します。FINISHEDenv varがないと、URLパスのホスト名のプレフィックスと削除が繰り返されるため、「不明なURL」の書き換えループでスタックします。

# Prefix URL-path with HTTP_HOST if not already prefixed and not FINISHED / No "L" flag
RewriteCond %{ENV:FINISHED} ^$
RewriteCond %{HTTP_HOST}@$1 !^([a-z.-]+)@\1 RewriteCond %{REQUEST_FILENAME} !-f RewriteRule (.*) %{HTTP_HOST}/$1

# :
# : Directives for each domain go here (as above)
# :

# Tidy up - remove the HTTP_HOST prefix and set FINISHED env var
RewriteCond %{HTTP_HOST}@$1 ^([a-z.-]+)@\1/(.*)
RewriteRule (.*) %2 [E=FINISHED:1,L]

3..htaccessホストごとに個別の構成ファイル

別々のドメインと本質的に別々のWebサイト(おそらく「共通の」エンジンですが)のこの特定の状況により適している可能性がある別の代替手段は.htaccess、サイトごとに追加の(別々の)ファイルを用意することです。

これをどのように構成するかは、ファイル構造をどのように構成したかによって異なりますが、これにより、サイト間の分離を強化し、必要に応じて2つ以上のサイト間で構成を共有することもできます。アクセスしているサイトだけに関連するリソースを持つこともできますが、すでにこのようなものがあるかもしれません。

例えば...

  • .htaccessドキュメントルートにはまだ「マスター」ファイルがあります(すべてのドメインに共通のルートディレクトリを共有していると仮定します)。
  • ホストごとにサブディレクトリを作成します。例えば。/domain1.com各サブディレクトリ内には、.htaccessそのドメインのファイルがあります。

ファイル構造:

/
    domain1.com/
        .htaccess
    domain2.com/
        .htaccess
    .htaccess
    index.php

/.htaccess

次に、ルート.htaccessファイルは、要求されたホストの適切なサブディレクトリに要求をルーティングします。

RewriteEngine On

# If the request is already for index.php in the document root then DONE
RewriteRule ^index\.php$ - [L]

# Rewrite all requests that don't map to files to the appropriate domain subdirectory
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*) %{HTTP_HOST}/$1 [L]

/domain1.com/.htaccess

次に、各ドメインの.htaccessファイルにはそのドメインのディレクティブのみが含まれ、リクエストを/index.phpドキュメントルートの「共通」ファイルに書き換えてリクエストをレンダリングします。

書き換えディレクティブは、上記で使用したものと同じ「通常の」形式を取ります。

# domain1.com

RewriteEngine On

# Optional - If this subdirectory is accessed directly then redirect back to the root
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule (.*) /$1 [R=301,L] #main pages RewriteRule ^members/$     /index.php?pageid=2 [NC,L]
RewriteRule ^contact/$ /index.php?pageid=3 [NC,L] RewriteRule ^affiliates/$  /index.php?pageid=4 [NC,L]

#blog articles
RewriteRule ^welcome-to-our-blog/$ /index.php?pageid=b0001 [NC,L]

とにかく、思考の糧。これの一部は、厳密に「RewriteCondによるRewriteRuleのグループ化」ではなく、アプリケーションの構造に帰着します。「ビット」についてさらに説明が必要な場合は、「ビット」とだけ言ってください。