Laravelで.htaccessを使わずに動作させる方法

Laravel

.htaccessはディレクトリ単位でApacheの設定ができて便利ですが、セキュリティやパフォーマンスを重視する場合には.htaccessを使用しないこともあります。

.htaccessを利用できない環境下でLaravelを使うには、Apacheをどのように設定すればよいか、解説します。

Laravelの.htaccess

まず、Laravelの.htaccessではどのような設定になっているかを確認しましょう。

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews -Indexes
    </IfModule>

    RewriteEngine On

    # Handle Authorization Header
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} (.+)/$
    RewriteRule ^ %1 [L,R=301]

    # Send Requests To Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
</IfModule>

.htaccessには、いろいろ書かれていますが、結局やっていることは3つです。

  1. 環境変数HTTP_AUTHORIZATIONを設定(FastCGI用)
  2. / で終わるURLを、/ がないURLへリダイレクト
  3. 静的ファイル以外、index.php で処理させる

.htaccessに書かれたこれらの内容をhttpd.confに移動して、動作させてみます。

httpd.confの<Directory>ディレクティブで設定する

.htaccessの内容を<Directory>ディレクティブ内に記述する方法がもっとも簡単です。

httpd.confには、次のように記述します。

Laravelのインストールディレクトリは /var/www/laravel で、ドキュメントルート /var/www/laravel/public がApacheに設定されているものとします。

<Directory /var/www/laravel/>
  Require all granted
  AllowOverride none

  # Laravelの設定はここから
  <IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
      Options -MultiViews -Indexes
    </IfModule>

    RewriteEngine On

    # Handle Authorization Header
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} (.+)/$
    RewriteRule ^ %1 [L,R=301]

    # Send Requests To Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ /index.php [L]
  </IfModule>

</Directory>

httpd.confの<VirtualHost>内でLaravelを設定する

<Directory>ディレクティブではなく、<Location>や<VirtualHost>内で設定することもできます。

httpd.confには、次のように記述します。

Laravelのインストールディレクトリは /var/www/laravel で、ドキュメントルート /var/www/laravel/public がApacheに設定されているものとします。

<VirtualHost *:80>
    ServerName example.com

    # Laravelの設定はここから
    Options -MultiViews -Indexes

    RewriteEngine On

    # Handle Authorization Header
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond /var/www/laravel/public%{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} (.+)/$
    RewriteRule ^ %1 [L,R=301]

    # Send Requests To Front Controller...
    RewriteCond /var/www/laravel/public%{REQUEST_FILENAME} !-d
    RewriteCond /var/www/laravel/public%{REQUEST_FILENAME} !-f
    RewriteRule ^ /index.php [L]
</VirtualHost>

.htaccessと記述を変更したのは、以下の2か所です。

  • %{REQUEST_FILENAME}の前にLaravelディレクトリを追加
  • リライトルールの最終URLを index.php から /index.php に変更

%{REQUEST_FILENAME}の前にLaravelディレクトリを追加

.htaccessで設定した内容を、httpd.confなどのサーバーレベルのファイルに設定を移動すると、そのまま動く場合もありますが、パスやディレクトリに関連した動作が変更されてしまいます。

RewriteCondディレクティブで使っている変数 %{REQUEST_FILENAME} もそのうちの一つで、.htaccessに記述した時と、httpd.confに記述したときとでは動作が異なります。

変数名.htaccessで記述した時httpd.confで記述した時の値
REQUEST_FILENAMEファイルの絶対パス
(例)/var/www/html/foo.html
リクエストURI
(例)/foo.html

そのため、%{REQUEST_FILENAME} の直前に /var/www/laravel/public というLaravelのドキュメントルートを指定しています。

サーバーレベルの設定ファイルでも、REQUEST_FILENAMEを使うには、%{LA-U:REQUEST_FILENAME}という記述を使う方法もあります。これは、URLからディレクトリパスへの評価を事前に(Look Ahead)行うというものですが、Laravelの設定ファイルではうまくいきません。%{LA-U:REQUEST_FILENAME}が/var/www/laravel/public/index.phpという実ファイルを参照しているとみなされるため、最後のリライトが行われず、404エラーになってしまいます。

最後のRewriteRuleを/index.phpに変更

Laravelの.htaccessでは、最終的にリクエストをindex.phpで処理させるようにURLをリライトしています。

また、RewriteRuleではリライト先URLを index.php と、同一ディレクトリ内のindex.phpで処理させるように指定しています。

RewriteRule ^ index.php [L]

ただし、この記述をサーバーレベルの設定ファイルに持っていくと、400 Bad Requestエラーとなってしまいます。

なぜなら、サーバーレベルの設定ファイルでは、リクエストURIがリライト対象となりますが、リライト後のURLが/から始まらないURIになるためです。

/で始まらないリクエストURIは、仕様上、許可されていません。リクエストURIは、/foo.html とか 、/assets/bundle.css とか /wp-admin/ とか、必ず / から始まりますよね。

そこで、リライト後のURLは /index.php のように指定します。

RewriteRule ^ /index.php [L]

どのディレクティブ内に移動するかによって設定変更が必要

以上、Laravelの.htaccessをhttpd.confに移動する方法を紹介しました。

注意が必要なのが、設定する場所に応じて内容を変更する必要がある点です。設定の違いに着目すれば、難なく正しく動作させることができます。

WordPressの.htaccessも同じ方法で移動できるはずなので、やってみてください。