[FuelPHP]フォルダ構成、環境変数とTaskの話

WEB

前提

WebサーバーにはApacheを使用しているものとします。

フォルダ構成について

フォルダ構成の変更

複数サイト対応したい場合や、サーバー側の制限でドキュメントルートを思うところに設定できない場合など、FuelPHPのフォルダ構成を変更したいときがありますね。
たとえば、デフォルトでは以下のようなフォルダ構成になっているので…

ルートディレクトリ/
 ├fuel/
 │  ├app/
 │  ├core/
 │  └packages/
 │
 └public/
    ├assets/
    └index.php

公開ディレクトリ(public以下)をルート直下に置くには、以下のようにフォルダ構成を変更します。

ルートディレクトリ/
 ├fuel/
 │  ├app/
 │  ├core/
 │  └packages/
 ├assets/
 └index.php

ここで、公開ディレクトリのindex.phpから見たfuelディレクトリ以下へのパスが変わっていますので変更してあげましょう。

index.phpで環境定数の定義を書き換えます。

index.php(before)
[php]
/**
 * Path to the application directory.
 */
define('APPPATH', realpath(__DIR__.'/../fuel/app/').DIRECTORY_SEPARATOR);
[/php]
index.php(after)
[php]
/**
 * Path to the application directory.
 */
define('APPPATH', realpath(__DIR__.'/fuel/app/').DIRECTORY_SEPARATOR);
[/php]
※PKGPATH, COREPATHも同様に変更します。

Oilコマンドを利用する場合

もしOilコマンドを利用してTaskを実行する予定があるなら、oilファイル内の環境定数もindex.phpと同様に変更する必要があります。

これも公式ドキュメントにある通りですけれども、初見で気づかないとちょっとハマってしまいます(ハマりました)。

注意: Oil パッケージを使う場合、Web サイトの docroot にある 'oil' ファイルに同じ変更を加える必要があります。

定数 - 概要 - FuelPHP ドキュメント

裏を返せばTaskではindex.phpと別の環境定数を使うことができるということでもありますね。

そんな機会あるのかな?

まあ必要なときはそうできる、ということで。

環境変数について

環境変数の変更

環境変数を変更することで、本番環境と開発環境といった環境ごとの動作を分けることができます。

本番環境用には「\Fuel::production」、開発環境には「\Fuel::development」という環境変数が用意されています。

そのほかの環境変数もあります。詳しくは公式マニュアルの「環境」ページを参照ください。

具体的には、読み込むconfigファイルを切り替えることでDBの接続先やフレームワークの動作を変更すること等ができます。

configファイルの切り替え

fuel/
 └app/
   └config/
     ├development/
     │  └config.php ←環境変数がdevelopmentのときに読み込まれます
     ├production/
     │  └config.php ←環境変数がproductionのときに読み込まれます
     └config.php    ←常に読み込まれます

configファイルの設定は、configディレクトリ直下のファイルに設定された内容と、環境変数毎に読み込まれるディレクトリ内のファイルに設定された内容がマージされます。

公式マニュアルでは、「設定」のページ「Configクラス」のページに記載があります。

環境変数を変更する方法

環境変数を変更するには以下の方法があります。

本番環境に設定するのであれば、

  • httpd.confまたは.htaccessで「SetEnv FUEL_ENV production」を行う
  • bootstrap.phpで「\Fuel:$env = \Fuel::PRODUCTION;」を行う

といった具合です。

ただし、httpd.confと.htaccessについては、環境によっては利用できない場合があります。

そんなときはbootstrap.phpで環境変数を設定してやるといいでしょう。

固定値を設定することもできますし、if文で分岐することもできます。

bootstrap.phpで、環境変数を動的に変更する

たとえば、特定のサーバーへアクセスされてきた場合のみ本番環境とするなら・・・

fuel/app/bootstrap.php
[php]
/**
 * 特定のサーバー名が含まれている場合に本番環境とする
 */
if($_SERVER['SERVER_NAME'] == 'honban.ne.jp')
{
    \Fuel::$env = \Fuel::PRODUCTION;
}
else
{
    \Fuel::$env = \Fuel::DEVELOPMENT;
}
[/php]

これでいいでしょう。

URLによって環境変数を動的に変更することができます。

ただしOilコマンドからTaskを実行する場合には? こうはいきません。

Task使用時の注意点

先に挙げた例ではうまくいきません。というのもコマンドから実行したときには$_SERVER['SERVER_NAME']が取得できないからです。

HTTPリクエストを受け付けてWebサーバーから実行されたのでないと$_SERVER['SERVER_NAME']には値が入らないんですね。

(コマンドから実行したのだから当然かもしれません。)

Task実行時に取得できる$_SERVER変数を出力して、試してみるといいでしょう。

というわけで、Task実行時にはその都度コマンドで環境変数を指定してやらないといけません。

[bash]
# 環境変数にproductionを設定する
$ env FUEL_ENV=production php oil -v
[/bash]

これも公式ドキュメントの通りではありますが。

ところが、Windows環境下では

開発環境がWindowsという場合も少なくないと思います。

かくいう私もWindowsで開発しています。

Windows10です。コマンドプロンプトや環境変数設定のUIが改善されていて地味に好きです。

それはさておき、コマンドプロンプトからOilコマンドを実行する際、環境変数の設定がうまくいきません。公式ドキュメントには、以下の例で環境変数が設定できたと書いてありますが・・・

[bash]
# 環境変数にproductionを設定する
C:\> set FUEL_ENV=production && php oil -v
[/bash]

手元のWindows環境では環境変数が設定できませんでした。

とはいえbootstrap.php内で決め打ちも(間違ってそのまま本番環境に上げてしまいそうで)嫌だ・・・

開発環境と本番環境を動的に切り分ける方法はないでしょうか?

開発環境はWindows、本番環境はそれ以外のOSという場合に限りますが

fuel/app/bootstrap.php
[php]
// $_SERVER変数に'SERVER_NAME'の値がある→HTTPリクエストから実行されている場合
if(isset($_SERVER['SERVER_NAME']))
{
    if($_SERVER['SERVER_NAME'] == 'honban.ne.jp')
    {
        // 本番環境のURLなので、環境変数にproductionを設定
        \Fuel::$env = \Fuel::PRODUCTION;
    }
    else
    {
        // 環境変数にdevelopmentを設定
        \Fuel::$env = \Fuel::DEVELOPMENT;
    }
}
// $_SERVER変数に'SERVER_NAME'の値がない→コマンドから実行されている場合
else
{
    // Windowsで実行されているか判定する
    if(defined('PHP_WINDOWS_VERSION_MAJOR'))
    {
        // Windowsで実行されていれば環境変数をdevelopmentとする
        \Fuel::$env = \Fuel::DEVELOPMENT;
    }
    else
    {
        // Windowsでなければコマンドで設定された環境変数を取得して設定する
        // もし設定されていなければdevelopmentとする
        \Fuel::$env = getenv('FUEL_ENV')?: \Fuel::DEVELOPMENT;
    }
}
[/php]

上記の形で、OSがWindowsの場合はdevelopment、Windowsでない場合はコマンドで指定された環境変数というように分岐することができます。

また、HTTPリクエストからの実行なのかコマンドからの実行なのかの分岐も入れてみました。

これで大丈夫とは思いますが、問題点やもっといい方法がありましたらぜひ教えてください。

PHP: defined - Manual
PHP is a popular general-purpose scripting language that powers everything from your blog to the most popular websites i...
PHP: getenv - Manual
PHP is a popular general-purpose scripting language that powers everything from your blog to the most popular websites i...

終わりに

Taskを利用することでcronで定期実行とか重たい処理を非同期で実行といったことができますが、その前段のところで躓くと意外に時間がとられてしまいます。

この記事がどなたかの時間をスペアすることになれば幸いです。

更新履歴

  • 2018/08/11 初版作成

コメント