概要
本業の仕事に限らず、今までやってきた中で環境の判定を行うメソッドを作ったことがある。
その中でこのようなことがあったよという共有。もちろんケースバイケースでこれ以外にも良い方法はあるのでは?と思ってもいるが、当たり障りがないという意味ではそうかなと思った。なのでまとめておく。
今回の話の大前提
今回は環境変数に環境の判定をする値を持たせている前提で話を進めます。
変数名 : ENVIRONMENT
値(開発環境) : DEVELOP
他にも方法はありますが、今回はこれで。
そもそも動的メソッドで何が悪いの?
全ての場合が悪いわけではない(と思っている)。駄菓子菓子辛い時もある。それが以下の時。
class Environment
{
public function isDevelopment() {
if (getenv('ENVIRONMENT') === 'DEVELOP') {
return true;
}
return false;
}
}
そしてそれを同じクラスで使おうとするとこうなる。
require_once('Environment.php');
class Environment
{
public function isDevelopment() {
if (getenv('ENVIRONMENT') === 'DEVELOP') {
return true;
}
return false;
}
public function sample1() {
$environment = $this->isDevelopment(); // 使うのはこの箇所。
if ($environment === true) {
// なんかやりたい処理
}
}
}
このsample1メソッドをstatic(静的メソッド)にしたいなとなった時に本当のつらみが召喚される。
public static function sample1() { // ここをstaticにした!
$environment = $this->isDevelopment();
if ($environment === true) {
// なんかやりたい処理
}
}
このメソッドを実行するとExceptionが発生するはず。
なぜなら静的メソッドの中でインスタンスを作って・・・といったことはできないからである。
@nunulk さんに指摘していただいた通り、できないのは$thisの参照でした・・・
$thisの何が悪いのか
$this はそもそもinstanceを作らないと使用できないもの。
つまりは $environment = new Environment() とかしないと使えないということ。
何が悪いのかというと、以下のような呼び出し方(静的な呼び出し方)ができない。
public function sample1() {
$is_development = self::isDevelopment(); // 左記のような静的な呼び出し方
if ($is_development === true) {
//開発環境でのみやりたい処理
}
}
この静的メソッドの呼び出しができないと、一時退避としてこのメソッドを動的メソッドのまま使って・・・となってsample1を使っているところも静的メソッドにすることが叶わなくなり・・・の無限ループとなる。
(実際静的メソッドにするとしてもそんなに依存関係を強くするなよという声が聞こえてきそうですが、すでに汚いコードに対して少しずつ綺麗にしようとするとそうなりがち)
環境を判定するメソッドを静的メソッドにしてみたバージョン
こうなると困らないよね。見た目もちょっとスッキリ。
class Sample
{
public static function sample1() {
if (self::isDevelopment() === true) {
// 開発環境でのみやりたい処理
}
}
}
別クラスで使う場合もスッキリ!
require_once('Environment.php')
class AnotherClassSample
{
public static function sample() {
if (Environment::isDevelopment() === true) {
// 開発環境でのみやりたい処理
}
}
}
まとめ
こういうことが起きないように、環境を判定するメソッドは、静的メソッドにした方が後から困らないと思いました。まる。