基礎

PHPの静的プロパティ・静的メソッド|staticキーワードの使い方

PHPの静的メンバー(static members)は、インスタンスを生成しなくてもクラス名から直接アクセスできるプロパティやメソッドです。static キーワードを付けて定義し、::(スコープ解決演算子)でアクセスします。

静的メンバーは全インスタンスで共有される値の管理や、インスタンス不要なユーティリティ関数の定義に使われます。クラス定数と似ていますが、静的プロパティは値を変更できる点が異なります。

基本的な使い方

PHP
<?php
class Counter {
    // 静的プロパティ(全インスタンスで共有)
    private static int $count = 0;

    public function __construct() {
        self::$count++;
    }

    // 静的メソッド(インスタンス不要で呼べる)
    public static function getCount(): int {
        return self::$count;
    }
}

echo "初期値: " . Counter::getCount() . "\n";

$a = new Counter();
$b = new Counter();
$c = new Counter();

echo "3つ生成後: " . Counter::getCount() . "\n";
実行結果
初期値: 0
3つ生成後: 3

静的プロパティ $count は全インスタンスで共有されるため、インスタンスを3つ作ると値が3になります。Counter::getCount() のようにインスタンスなしで呼べます。

selfとstaticの違い

クラス内から静的メンバーにアクセスするとき、selfstatic で挙動が変わります。

PHP
<?php
class ParentClass {
    protected static string $name = "Parent";

    public static function showSelf(): string {
        return self::$name;    // 常にParentClassの値
    }

    public static function showStatic(): string {
        return static::$name;  // 呼び出し元クラスの値(遅延静的束縛)
    }
}

class ChildClass extends ParentClass {
    protected static string $name = "Child";
}

echo "self: " . ChildClass::showSelf() . "\n";
echo "static: " . ChildClass::showStatic() . "\n";
実行結果
self: Parent
static: Child

self はメソッドが定義されたクラスを、static は実行時の呼び出し元クラスを参照します。継承を活用する場合は static を使うのが一般的です。

ユーティリティクラス

静的メソッドのみで構成されるユーティリティクラスは、よく使うパターンです。

PHP
<?php
class StringHelper {
    public static function truncate(string $text, int $length, string $suffix = "..."): string {
        if (mb_strlen($text) <= $length) {
            return $text;
        }
        return mb_substr($text, 0, $length) . $suffix;
    }

    public static function toCamelCase(string $text): string {
        return lcfirst(str_replace(" ", "", ucwords(str_replace("_", " ", $text))));
    }

    public static function toSnakeCase(string $text): string {
        return strtolower(preg_replace('/[A-Z]/', '_$0', lcfirst($text)));
    }
}

echo StringHelper::truncate("PHPのクラスについて詳しく解説します", 10) . "\n";
echo StringHelper::toCamelCase("user_first_name") . "\n";
echo StringHelper::toSnakeCase("userFirstName") . "\n";
実行結果
PHPのクラスにつ...
userFirstName
user_first_name

実用的な例

PHP
<?php
class Config {
    private static array $settings = [];

    public static function set(string $key, mixed $value): void {
        self::$settings[$key] = $value;
    }

    public static function get(string $key, mixed $default = null): mixed {
        return self::$settings[$key] ?? $default;
    }

    public static function has(string $key): bool {
        return isset(self::$settings[$key]);
    }

    public static function all(): array {
        return self::$settings;
    }
}

Config::set("app_name", "MyApp");
Config::set("debug", true);
Config::set("version", "1.0.0");

echo Config::get("app_name") . "\n";
echo Config::get("db_host", "localhost") . "\n";
echo "debug: " . var_export(Config::has("debug"), true) . "\n";
print_r(Config::all());
実行結果
MyApp
localhost
debug: true
Array
(
    [app_name] => MyApp
    [debug] => 1
    [version] => 1.0.0
)
ポイント

静的メソッド内では $this は使えません(インスタンスが存在しないため)。代わりに self:: または static:: で静的メンバーにアクセスします。

注意

静的メンバーはグローバル状態を作りやすく、テストが困難になる場合があります。ユーティリティ関数やファクトリメソッドには適していますが、状態を持つ処理にはインスタンスメソッドを使う方が保守性が高くなります。

まとめ

  • static キーワードで静的プロパティ・メソッドを定義する
  • クラス名::メンバー名 でインスタンスなしにアクセスできる
  • self は定義元、static は実行時のクラスを参照する
  • ユーティリティクラスや設定管理に適している
  • 静的メソッド内では $this は使用できない