LoginSignup
7
6

More than 5 years have passed since last update.

PHP < 5.3 の遅延静的束縛

Posted at

PHP < 5.3の環境でどうしても遅延静的束縛を使った実装がしたくていろいろ調べてみました。

結論

ほぼむりそうでした。うまいことできそうだったら教えてください。

遅延静的束縛について

そもそも遅延静的束縛というのは、以下のようなかんじでstaticな継承コンテキストで、呼び出しもとのクラスを参照できるというもの。

static.php
class Member
{
    public static function getInstance()
    {
        return new static;
    }
}
class Leader extends Member {}

echo get_class(Member::getInstance()), PHP_EOL; // Member
echo get_class(Leader::getInstance()), PHP_EOL; // Leader

このstatic::という呼び出し方で、呼び出しもとの値を参照できて、static::$_propertyとかstatic::hogeFunction()とかっていうことができる。

これをself::で書くと以下のような感じで、selfが書かれたクラスを参照してしまう。

self.php
class Member
{
    public static function getInstance()
    {
        return new self;
    }
}
class Leader extends Member {}

echo get_class(Member::getInstance()), PHP_EOL; // Member
echo get_class(Leader::getInstance()), PHP_EOL; // Member

php < 5.3では静的遅延束縛をサポートされていないので、なんとかできないものかと調べてみたけど、どうもいけてる解決策がなかった。

呼び出し元のクラス名さえわかれば、call_user_func(array($class_name, $function_name))とか駆使してなんとかいけるんだけど、呼び出しもとを取得するget_called_class()という関数もphp >= 5.3でのサポート。

ということで詰みました。

いちおういけてない妥協案をいくつか

1. 全クラスに書く

bad_solution_1.php
class Member
{
    public static function getInstance()
    {
        return new self;
    }
}
class Leader extends Member
{
    public static function getInstance()
    {
        return new self;
    }
}

echo get_class(Member::getInstance()), PHP_EOL; // Member
echo get_class(Leader::getInstance()), PHP_EOL; // Leader

DRY原則とはなんだったのか!

2. class名を引数で渡す

bad_solution_2.php
class Member
{
    public static function getInstance($class_name)
    {
        return new $class_name;
    }
}
class Leader extends Member {}

echo get_class(Member::getInstance('Member')), PHP_EOL; // Member
echo get_class(Leader::getInstance('Leader')), PHP_EOL; // Leader

staticに呼び出しているということはクラス名はわかっているはずなので、解決策1よりは行けてる気がする。ただ、全く関係ないクラスのfunctionも実行できてしまうという諸刃の剣。(ReflectionClassとか使ってチェックすれば防げるといえば防げる気はする)

3. debug_backtraceから呼び出し元classを取得する

このサイトに書いてあるやつ。

debug_backtraceから呼び出し元ファイルを行数指定で取得して、正規表現にマッチさせてクラス名を取得するという豪快な技。

すごいけど、コストが高そう。

4. php >= 5.3にする

最強の解決策

7
6
0

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
7
6