静的プロパティとメソッド——インスタンスなしで使えるもの
static とは何か
これまでのクラスは new でインスタンスを作ってから使っていました。しかし「インスタンスを作るほどでもない、クラスにまとめておきたい便利な関数」というものがあります。
静的(static)メソッドやプロパティは、インスタンスを作らずにクラスから直接使えます。
class MathHelper
{
public static function add(int $a, int $b): int
{
return $a + $b;
}
public static function multiply(int $a, int $b): int
{
return $a * $b;
}
}
// new MathHelper() は不要
echo MathHelper::add(3, 5); // 8
echo MathHelper::multiply(4, 6); // 24
クラス名::メソッド名() という :: 演算子(スコープ解決演算子)で呼び出します。
静的プロパティ
静的プロパティはクラス全体で共有される変数です。どのインスタンスからアクセスしても同じ値を参照します。
class Counter
{
private static int $count = 0;
public static function increment(): void
{
self::$count++;
}
public static function getCount(): int
{
return self::$count;
}
}
Counter::increment();
Counter::increment();
Counter::increment();
echo Counter::getCount(); // 3
self::$プロパティ名 でクラス内から静的プロパティにアクセスします。
インスタンスプロパティとの違い
class Person
{
public static int $totalCount = 0; // クラス全体で共有
public string $name; // インスタンスごとに別
public function __construct(string $name)
{
$this->name = $name;
self::$totalCount++; // 人が増えるたびにカウント
}
}
$alice = new Person('Alice');
$bob = new Person('Bob');
echo Person::$totalCount; // 2(全インスタンスで共有)
echo $alice->name; // Alice(このインスタンスだけ)
echo $bob->name; // Bob(このインスタンスだけ)
クラス定数
変わることのない値はクラス定数で定義します。const キーワードを使います。
class HttpStatus
{
const OK = 200;
const CREATED = 201;
const BAD_REQUEST = 400;
const UNAUTHORIZED = 401;
const NOT_FOUND = 404;
const INTERNAL_SERVER_ERROR = 500;
}
function sendResponse(int $statusCode, mixed $data): void
{
http_response_code($statusCode);
echo json_encode($data);
}
sendResponse(HttpStatus::OK, ['message' => 'Success']);
sendResponse(HttpStatus::NOT_FOUND, ['error' => 'Resource not found']);
マジックナンバー(意味不明な数字)をコードに直接書く代わりに定数を使うと、コードの意図が明確になります。
PHP 8.3 の型付き定数
PHP 8.3から定数に型を付けられます。
class Config
{
const int MAX_RETRY = 3;
const string APP_NAME = 'MyApp';
const float TAX_RATE = 0.1;
}
ユーティリティクラス
関連するユーティリティ関数をまとめたクラスです。インスタンス化は想定しないため、コンストラクタを private にして直接インスタンス化できないようにします。
class StringHelper
{
// インスタンス化を禁止
private function __construct() {}
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 toSnakeCase(string $str): string
{
return strtolower(preg_replace('/[A-Z]/', '_$0', lcfirst($str)));
}
public static function toCamelCase(string $str): string
{
return lcfirst(str_replace('_', '', ucwords($str, '_')));
}
}
echo StringHelper::truncate('オブジェクト指向プログラミング入門', 10);
// オブジェクト指向プロ...
echo StringHelper::toSnakeCase('myVariableName');
// my_variable_name
echo StringHelper::toCamelCase('my_variable_name');
// myVariableName
シングルトンパターン入門
シングルトンはアプリケーション全体で「インスタンスが1つだけ」であることを保証するパターンです。設定クラスやログクラスに使われます。
class AppConfig
{
private static ?AppConfig $instance = null;
private array $settings = [];
// コンストラクタを private に → 外から new できない
private function __construct()
{
// 設定ファイルを読み込む
$this->settings = [
'app_name' => 'MyApp',
'debug' => false,
'timezone' => 'Asia/Tokyo',
];
}
// クローンも禁止
private function __clone() {}
// 唯一のインスタンスを返す
public static function getInstance(): static
{
if (static::$instance === null) {
static::$instance = new static();
}
return static::$instance;
}
public function get(string $key, mixed $default = null): mixed
{
return $this->settings[$key] ?? $default;
}
public function set(string $key, mixed $value): void
{
$this->settings[$key] = $value;
}
}
$config1 = AppConfig::getInstance();
$config2 = AppConfig::getInstance();
var_dump($config1 === $config2); // bool(true):同じインスタンス
$config1->set('debug', true);
echo $config2->get('debug') ? 'true' : 'false'; // true(同じインスタンスなので)
シングルトンの注意点
シングルトンは便利ですが、テストが難しくなるという欠点があります。グローバル状態を持つため、テスト間で状態が残ってしまうことがあります。現代的なPHP開発ではDIコンテナ(第9回で解説)でインスタンス管理することが多く、シングルトンパターンの使用頻度は下がっています。
self と static の違い
静的メソッド内で self:: と static:: は微妙に異なります。
class Base
{
public static function create(): static
{
return new static(); // static:: = 実際に呼ばれたクラス
}
public static function className(): string
{
return static::class; // 遅延静的束縛
}
}
class Child extends Base {}
$base = Base::create(); // Base のインスタンス
$child = Child::create(); // Child のインスタンス
echo Base::className(); // Base
echo Child::className(); // Child
static:: は「実際に呼ばれたクラス」を指します(遅延静的束縛)。継承と組み合わせるときは static:: を使うことが多いです。
まとめ
staticメソッド・プロパティはインスタンスなしにクラス名::で呼び出す- 静的プロパティはクラス全体で共有される
constで定数を定義してマジックナンバーを排除する- ユーティリティクラスのコンストラクタは
privateにしてインスタンス化を禁止する - シングルトンパターンはインスタンスが1つだけになることを保証する(テストへの注意が必要)
self::はクラス定義時のクラス、static::は呼び出し時のクラスを指す
次回は名前空間とオートローディング——大きなプロジェクトでのファイル・クラス整理術を学びます。