tohokuaikiのチラシの裏

技術的ネタとか。

PHPのself::とstatic::の違い

PHP: static キーワード - Manualのコメント読んでわかったのでメモ。

<?php
class a {

    static protected $test="class a\n";

    public function static_test(){

        echo static::$test;
        echo self::$test;

    }

}

class b extends a {

    static protected $test="class b\n";

}

$obj = new a();
$obj->static_test();

echo "\n";

$obj = new b();
$obj->static_test();
?>

$ php static_test.php
class a
class a

class b
class a
  • static::$foo は、上書きされる可能性がある
  • self::$foo は、上書きされない基底クラスのstaticを読みに行く

なんつーか、感覚的には逆な感じのするキーワードだな。

追記。自分の中でfunctionが定義されている場合は、selfも上書きされる

<?php
class A
{
    const HOGE = "hoge";
    const UKI = "uki";

    function printx()
    {
        print "\n\nconst test \n\n";
        printf("self HOGE => %s\n", self::HOGE);
        printf("self UKI => %s\n", self::UKI);
        printf("static HOGE => %s\n", static::HOGE);
        printf("static UKI => %s\n", static::UKI);
    }
}

class B extends A{
    const HOGE = "hoge a";
    const UKI = "uki a";
}

class C extends A{
    const HOGE = "hoge c";
    const UKI = "uki c";
}

B::printx();

C::printx();

const test

self HOGE => hoge
self UKI => uki
static HOGE => hoge a
static UKI => uki a


const test

self HOGE => hoge
self UKI => uki
static HOGE => hoge c
static UKI => uki c

というように、上書きされないselfであるが

<?php
class A
{
    const HOGE = "hoge";
    const UKI = "uki";

    function printx()
    {
        print "\n\nconst test \n\n";
        printf("self HOGE => %s\n", self::HOGE);
        printf("self UKI => %s\n", self::UKI);
        printf("static HOGE => %s\n", static::HOGE);
        printf("static UKI => %s\n", static::UKI);
    }
}

class B extends A{
    const HOGE = "hoge a";
    const UKI = "uki a";
      
    function printx()
    {
        print "\n\nconst test \n\n";
        printf("self HOGE => %s\n", self::HOGE);
        printf("self UKI => %s\n", self::UKI);
        printf("static HOGE => %s\n", static::HOGE);
        printf("static UKI => %s\n", static::UKI);
    }
}

class C extends A{
    const HOGE = "hoge c";
    const UKI = "uki c";
    
    function printx()
    {
        print "\n\nconst test \n\n";
        printf("self HOGE => %s\n", self::HOGE);
        printf("self UKI => %s\n", self::UKI);
        printf("static HOGE => %s\n", static::HOGE);
        printf("static UKI => %s\n", static::UKI);
    }
    
}

B::printx();

C::printx();

const test

self HOGE => hoge a
self UKI => uki a
static HOGE => hoge a
static UKI => uki a


const test

self HOGE => hoge c
self UKI => uki c
static HOGE => hoge c
static UKI => uki c

となる。

ということで

self::は、functionが定義されているクラスのものを見に行く、staticはそのfunctionが呼び出された時点での定義を見に行く。

というように考えればいいのではないか。分かりやすい。