LoginSignup
9
8

More than 5 years have passed since last update.

CodeIgniter4 の 環境/環境変数/設定 (Config) の使い方

Last updated at Posted at 2017-09-28

CodeIgniter4 メモ。
CodeIgniter4 User Guide を参考にしながら、必要に応じてソースを読み解き、挙動を追って理解を深めようと思います。

Attention

2017/09/23 現在 開発版の CodeIgniter4 についての記事です。リリースまでに変更される可能性があることをご承知おきの上、お読み下さい。

使用している commit: 8eba1da1f194e5124d87cc4d3b5c75e68af1ad44

TL;DR

  • .envCI_ENVIRONMENT を設定しない。
  • 環境に依存する Config 以下の設定は .env に設定する

環境 (Environment)

User Guide: Handling Multiple Environments

環境を CodeIgniter に伝えるには、次の二つがあります。

  1. .env ファイルに記述
  2. Webサーバーに環境変数を設定
    • Apache であれば SetEnv CI_ENVIRONMENT development
    • nginx であれば fastcgi_param CI_ENVIRONMENT development

この CI_ENVIRONMENT は、下記で 定数 ENVIRONMENT に設定されます。

framework/system/CodeIgniter.php
    protected function detectEnvironment()
    {
        // running under Continuous Integration server?
        if (getenv('CI') !== false)
        {
            define('ENVIRONMENT', 'testing');
        }
        else
        {
            define('ENVIRONMENT', $_SERVER['CI_ENVIRONMENT'] ?? 'production');
        }
    }

CI_ENVIRONMENT が設定されていなければ、production として動作します。
ちなみに、getenv('CI') の CI とは、CodeIgniter ではなく、Continuous Integration の意味ですね。framework/.travis.yml に設定されていました。

.env と Web サーバー、どちらが優先される?

Apache/nginx 等の Web サーバーに設定された環境変数は、PHP では $_SERVER に格納され、使用できますが、.env にも CI_ENVIRONMENT を設定していた場合、どちらが優先されるのでしょう?

実際に環境変数をセットしているのは、下記の箇所です。

framework/system/Config/Dotenv.php
    protected function setVariable(string $name, string $value = '')
    {
        list($name, $value) = $this->normaliseVariable($name, $value);

        if ( ! getenv($name, true))
            putenv("$name=$value");
        if (empty($_ENV[$name]))
            $_ENV[$name] = $value;
        if (empty($_SERVER[$name]))
            $_SERVER[$name] = $value;
    }

$_ENV, $_SERVER それぞれ、その環境変数名が空だったら、値をセットするようになっています。なので、 Web サーバーの設定値が優先されます。

.env に書いてあるのに、環境が切り替わらない〜」 とハマらないためにも、どこで設定するかのルールを決めた方がよいでしょう。

追記

User Guide に書いてありましたね。

If the variable exists in the environment already, it will NOT be overwritten.

意訳

すでに環境変数が設定されていたら、変数は上書きしません。

追記ここまで

どの方法で CI_ENVIRONMENT を設定するか?

ここでは、本番・ステージング・ローカル開発の3つを切り替えたいと思います。

今や仮想化、コンテナ、Infrastructure as Code があるため、本番とステージングの構成に差異は無いという前提にします。

本番 (production)

$_SERVER['CI_ENVIRONMENT'] が設定されていなければ、production として扱うため、何も設定しません。

本番環境は、「しなくていいことは極力しない」ほうが良いと考えています。

ステージング (staging)

前述のとおり、本番と差はありません。ですが、後述のローカル開発環境との兼ね合いで、.envには書きたくありません。

なので、ここは Web サーバーに任せようと思います。

.htaccess に書くのも手ではありますが、nginx になると使えません。なので、もうサーバーの設定ファイルに書くことにします。

/etc/httpd/conf.d/apache_staging.conf
SetEnv CI_ENVIRONMENT development
/etc/nginx/conf.d/nginx_staging.conf
fastcgi_param CI_ENVIRONMENT "development";

専用のサーバーを設置していると思うので、グローバルなスコープで定義してしまいます。
これらのファイルをサーバー構築時に設置するだけでよいので、最もお手軽かと。

ローカル開発 (development)

CodeIgniter4 にはローカル開発環境のための serve スクリプトが付属しています。

php serve

と実行すると、ビルトインサーバーを使って http://localhost:8080/ で動作します。
この時、ルータースクリプトとして、rewrite.php を指定されており、その中で

$_SERVER['CI_ENVIRONMENT'] = 'development';

と、 CI_ENVIRONMENT が設定されています。.env に書きたくない、というのはココにあります。

前述の

$_ENV, $_SERVER それぞれ、その環境変数名が空だったら、値をセットするようになっています。なので、 Web サーバーの設定値が優先されます。

を思い出して下さい。そうです、$_SERVER['CI_ENVIRONMENT'] には値がセットされているので、.envCI_ENVIRONMENT を設定しても、development となります。

仮に、.envCI_ENVIRONMENT = "hoge" として serve から起動した場合、

var_dump($_SERVER['CI_ENVIRONMENT']); // "development"
var_dump($_ENV['CI_ENVIRONMENT'] // "hoge"

という、チグハグな状態になります。作りとしては、これら二値は同じ値であることが前提と思われるので、この運用はよろしくない。
いずれの環境においても、.envCI_ENVIRONMENT を設定しない
とするのが正のように思います。


設定 (Config)

User Guide: Working With Configuration Files

User Guide に従い、データベースの設定を読み出してみます

$db_config = new \Config\Database();
var_dump($db_config);
object(Config\Database)[40]
  public 'filesPath' => string '/XXX/XXX/XXX/application/Database/' (length=47)
  public 'defaultGroup' => string 'default' (length=7)
  public 'default' => 
    array (size=19)
      'DSN' => string '' (length=0)
      'hostname' => string 'localhost' (length=9)
      'username' => string '' (length=0)
      'password' => string '' (length=0)
      'database' => string '' (length=0)
      'DBDriver' => string 'MySQLi' (length=6)
      'DBPrefix' => string '' (length=0)
      'pConnect' => boolean false
      'DBDebug' => boolean true
      'cacheOn' => boolean false
      'cacheDir' => string '' (length=0)
      'charset' => string 'utf8' (length=4)
      'DBCollat' => string 'utf8_general_ci' (length=15)
      'swapPre' => string '' (length=0)
      'encrypt' => boolean false
      'compress' => boolean false
      'strictOn' => boolean false
      'failover' => 
        array (size=0)
          empty
      'port' => int 3306
  public 'tests' => 
    array (size=19)
      'DSN' => string '' (length=0)
      'hostname' => string '127.0.0.1' (length=9)
      'username' => string '' (length=0)
      'password' => string '' (length=0)
      'database' => string '' (length=0)
      'DBDriver' => string '' (length=0)
      'DBPrefix' => string 'db_' (length=3)
      'pConnect' => boolean false
      'DBDebug' => boolean true
      'cacheOn' => boolean false
      'cacheDir' => string '' (length=0)
      'charset' => string 'utf8' (length=4)
      'DBCollat' => string 'utf8_general_ci' (length=15)
      'swapPre' => string '' (length=0)
      'encrypt' => boolean false
      'compress' => boolean false
      'strictOn' => boolean false
      'failover' => 
        array (size=0)
          empty
      'port' => int 3306
  protected 'registrars' => null

application/Config/Database.php の値が取得できています。というか、クラスまんまですね。

User Guide によれば、自作の設定ファイルを作ることができるそうです。以下 User Guide から引用。

application/Config/App.php
<?php namespace Config;

class App extends \CodeIgniter\Config\BaseConfig {

        public $siteName = 'My Great Site';
        public $siteEmail = 'webmaster@example.com';

}

ただし、 application/Config/App.php, \Config\App はデフォルトで用意されていて、コアで使われているので別の名前にする必要があります。(User Guide も違う例文にしたほうが良いと思う…)

さらに、特に影響のない範囲ですが、デフォルトの Config では use CodeIgniter\Config\BaseConfig; しています。できれば前へ倣えしたほうがいいかと。

環境ごとの設定

どの環境でも同じ設定値で済むものについては、application/Config/ 以下に設定していけばよいですが、先述のデータベースなどは、本番と開発で接続先が異なることがほとんどです。

その取り回しについては、前項 環境 (Environment) で言及している .env が使えます。

CI_ENVIRONMENT.env に設定しないことを決めましたが、他方、設定値についてはとても有用です。

単純な使い方として、

.env
HOGE_VAR=hoge
$hoge_var = getenv('HOGE_VAR');
$hoge_var = $_SERVER['HOGE_VAR'];
$hoge_var = $_ENV['HOGE_VAR'];

というふうに使えるよう、環境変数にセットされます。

ここで紹介したい、便利な使い方は、.env から Config に値を設定する方法です。(もちろん、User Guide に書いてありますが)

データベースの接続設定を例にします。

.env
# Database
database.default.hostname = "localhost"
database.default.port = "3306"
database.default.username = "mysql_user"
database.default.password = "mysql_pass"
database.default.database = "app_db"
database.default.DBDriver = "MySQLi"

application/Config/Database.php についてはデフォルトのまま変更せず、先ほどと同じように設定値を var_dump してみます。 (長いので $db_config->default のみ抜粋)

array (size=19)
  'DSN' => string '' (length=0)
  'hostname' => string 'localhost' (length=9)
  'username' => string 'mysql_user' (length=10)
  'password' => string 'mysql_pass' (length=10)
  'database' => string 'app_db' (length=6)
  'DBDriver' => string 'MySQLi' (length=6)
  'DBPrefix' => string '' (length=0)
  'pConnect' => boolean false
  'DBDebug' => boolean true
  'cacheOn' => boolean false
  'cacheDir' => string '' (length=0)
  'charset' => string 'utf8' (length=4)
  'DBCollat' => string 'utf8_general_ci' (length=15)
  'swapPre' => string '' (length=0)
  'encrypt' => boolean false
  'compress' => boolean false
  'strictOn' => boolean false
  'failover' => 
    array (size=0)
      empty
  'port' => string '3306' (length=4)

ご覧の通り、値が変わりました。. でつなげてネストすることで、配列の値が設定されます。

あとは、本番、開発などの環境ごとに .env が変わればよいわけですね。

環境変数に値を設定することもできるし、CodeIgniter の Config の値を設定することもできるので、たとえば AWS などのサービスで使う 取扱いに注意しなければならないキーやパスワード.env ひとつにまとめることができます。

当然のことながら、この .env は バージョン管理に含めてはならない運用が必要です。

application/Config/*.php を編集する必要

.env で設定を管理するにしても、デフォルトで用意されていない値の場合、そのクラスのプロパティは宣言しておくとよいでしょう。たとえば、Apphoge という設定を作るとします。

app.hoge = "HogeHoge"

.env はこれでいいとして、\Config\App にも hoge を追加しましょう。

application/Config/App.php
<?php namespace Config;

use CodeIgniter\Config\BaseConfig;

class App extends BaseConfig
{
// ...略...
    public $hoge = 'default';
// ...略...
}

確実に .env に設定する ことが保証されるなら、問題はありません。しかし、前述のとおりバージョン管理に含めないので、プロパティを追加することで 「どんな設定値を追加したか」 のログができます。
デフォルト値も設定しておけば、フェイルセーフとして機能するかもしれません。

また、IDEがプロパティがあることを認識するので、補完が効くようになります。


まとめ

以上、CodeIgniter4 での環境切替/設定の取り回しについてまとめてみました。

先日 参加させていただいた CodeIgniter Night (第4回) で聞いた、「User Guide に書かれていることがすべて」 のとおりで、この記事は結局 User Guide の焼き直しみたいなものでした。

しかし、CodeIgniter はだいぶ自由度が高い印象を受けます。なので、自分が考える 「きれいな」 とか 「安全な」 開発運用のため、必要と思ったのでまとめた次第です。
これから CodeIgniter を使う誰かの一助にでもなれば。

9
8
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
8