PHP の static と self の違い

PHP の staticself の違いについてです。 基本中の基本なのですが、 PHP を書かない日が続くとどちらがどちらなのか忘れてしまい調べ直すことしきりなので、メモとして残しておきます。

まとめ

  • static実行時 のクラスを指す
  • self定義時 のクラスを指す

詳細説明

static は実行時の文脈でのクラスを指します。 つまり、 static の利用場所が static メソッドの場合はレシーバのクラスを、通常のインスタンスメソッドの場合はレシーバはオブジェクトなのでそのクラスを指します。

他方の self は定義時の文脈でのクラスを指します。

コードで確認してみましょう。 次のコードでは staticself の両方を使用しておりその違いを確認することができます。

class User
{

  public static function loadByName($name)
  {
    $id = self::getIdForName($name);
    return new static($id);
  }

  public static function getIdForName()
  {
    print __METHOD__ . PHP_EOL;
  }

  public function __construct($id)
  {
    print __METHOD__ . PHP_EOL;
  }

}

class AdminUser extends User
{

  public static function getIdForName()
  {
    print __METHOD__ . PHP_EOL;
  }

  public function __construct($id)
  {
    print __METHOD__ . PHP_EOL;
  }

}

$admin1 = AdminUser::loadByName('ラファエロ');
// =>
// User::getIdForName
// AdminUser::__construct

getIdForName() の呼び出しには self が使われているため、 AdminUser から loadByName() が呼ばれたと場合でも呼び出されるメソッドは UsergetIdForName() です( AdminUsergetIdForName() ではありません)。 一方、 __construct() の呼び出しには( new static() の形で) static が使われているため、 AdminUser から loadByName が呼ばれたときには AdminUser__construct() が使われます。

ちなみに、 static のこの挙動は late static binding と呼ばれたりするようです(漢字にするとかえって意味がわかりづらいので英語のままで……)。

個人的に、 self の方は直感的ですんなり頭に入ってきますが、 static は「それは言葉の意味として違うんじゃないか」という気がして仕方ありません。 PHP はこういうところが多いのが使っていて辛いところです :(