PHPのアクセス修飾子は、クラスのプロパティやメソッドへのアクセス範囲を制御するキーワードです。public(どこからでもアクセス可能)、protected(自クラスと子クラスからのみ)、private(自クラスからのみ)の3種類があります。
アクセス修飾子を適切に設定することで、クラスの内部実装を外部から隠蔽し、意図しない変更を防ぐカプセル化を実現できます。これはオブジェクト指向設計の基本原則のひとつです。
基本的な使い方
PHP
<?php
class User {
public string $name; // どこからでもアクセス可能
protected string $email; // 自クラスと子クラスのみ
private string $password; // 自クラスのみ
public function __construct(string $name, string $email, string $password) {
$this->name = $name;
$this->email = $email;
$this->password = password_hash($password, PASSWORD_DEFAULT);
}
public function getEmail(): string {
return $this->email;
}
public function verifyPassword(string $input): bool {
return password_verify($input, $this->password);
}
}
$user = new User("田中", "tanaka@example.com", "secret123");
echo $user->name . "\n"; // OK: public
echo $user->getEmail() . "\n"; // OK: publicメソッド経由
// echo $user->email; // Error: protected
// echo $user->password; // Error: private
echo "パスワード検証: " . ($user->verifyPassword("secret123") ? "成功" : "失敗") . "\n";
実行結果
田中
tanaka@example.com
パスワード検証: 成功
アクセス範囲の比較
PHP
<?php
class ParentClass {
public string $pub = "public";
protected string $prot = "protected";
private string $priv = "private";
public function showAll(): void {
// 自クラス内:すべてアクセス可能
echo "自クラス: {$this->pub}, {$this->prot}, {$this->priv}\n";
}
}
class ChildClass extends ParentClass {
public function showFromChild(): void {
echo "子クラス: {$this->pub}, {$this->prot}\n";
// echo $this->priv; // Error: private は子クラスからもアクセス不可
}
}
$parent = new ParentClass();
$parent->showAll();
$child = new ChildClass();
$child->showFromChild();
// 外部からのアクセス
echo "外部: {$parent->pub}\n";
// echo $parent->prot; // Error
// echo $parent->priv; // Error
実行結果
自クラス: public, protected, private
子クラス: public, protected
外部: public
この表がアクセス範囲をまとめたものです。
アクセス範囲の一覧
public:自クラス ○ / 子クラス ○ / 外部 ○
protected:自クラス ○ / 子クラス ○ / 外部 ×
private:自クラス ○ / 子クラス × / 外部 ×
getter/setterパターン
privateプロパティに対してpublicなgetter/setterメソッドを用意する設計パターンです。
PHP
<?php
class Temperature {
private float $celsius;
public function __construct(float $celsius) {
$this->setCelsius($celsius);
}
public function getCelsius(): float {
return $this->celsius;
}
public function setCelsius(float $value): void {
if ($value < -273.15) {
throw new InvalidArgumentException("絶対零度以下は設定できません");
}
$this->celsius = $value;
}
public function getFahrenheit(): float {
return $this->celsius * 9 / 5 + 32;
}
}
$temp = new Temperature(100);
echo "{$temp->getCelsius()}°C = {$temp->getFahrenheit()}°F\n";
$temp->setCelsius(0);
echo "{$temp->getCelsius()}°C = {$temp->getFahrenheit()}°F\n";
try {
$temp->setCelsius(-300);
} catch (InvalidArgumentException $e) {
echo "エラー: {$e->getMessage()}\n";
}
実行結果
100°C = 212°F
0°C = 32°F
エラー: 絶対零度以下は設定できません
実用的な例
PHP
<?php
class DatabaseConnection {
private static ?self $instance = null;
private string $status = "disconnected";
// privateコンストラクタ:外部からのnewを禁止
private function __construct(
private string $host,
private string $dbName
) {
$this->status = "connected";
}
// シングルトンパターン
public static function getInstance(string $host = "localhost", string $db = "app"): self {
if (self::$instance === null) {
self::$instance = new self($host, $db);
}
return self::$instance;
}
public function getStatus(): string {
return "{$this->host}/{$this->dbName}: {$this->status}";
}
}
$db1 = DatabaseConnection::getInstance("localhost", "myapp");
$db2 = DatabaseConnection::getInstance(); // 同じインスタンス
echo $db1->getStatus() . "\n";
echo ($db1 === $db2 ? "同一インスタンス" : "別インスタンス") . "\n";
実行結果
localhost/myapp: connected
同一インスタンス
設計の指針
迷ったらまず private にして、必要に応じて公開範囲を広げましょう。一度 public にしたプロパティを後から private に変更すると、利用側のコードが壊れる可能性があります。最初は厳しく制限し、必要に応じて緩める方が安全です。
まとめ
public:どこからでもアクセス可能protected:自クラスと子クラスからのみアクセス可能private:自クラスからのみアクセス可能- getter/setterパターンでバリデーション付きのアクセスを提供できる
- まず
privateで始め、必要に応じて公開範囲を広げるのが設計のコツ