【PHP】Lesson5-3:アクセス修飾子とカプセル化を理解しよう

一つ前のレッスンでは コンストラクタ について学習しました。
今回は アクセス修飾子とカプセル化 について見ていきましょう。
Lesson1:基礎文法編
Lesson2:制御構造編
Lesson3:関数編
Lesson4:データ構造編
Lesson5:クラス編
 ・Lesson5-1:クラスを定義しよう
 ・Lesson5-2:コンストラクタを理解しよう
 ・Lesson5-3:アクセス修飾子とカプセル化を理解しよう ◁今回はココ
 ・Lesson5-4:クラスメンバを理解しよう
 ・Lesson5-5:クラスの継承を理解しよう
 ・Lesson5-6:メソッドのオーバーライドを理解しよう
 ・Lesson5-7:抽象クラスを理解しよう
 ・Lesson5-8:インターフェースを理解しよう
 ・Lesson5-9:トレイトを理解しよう
 ・確認問題5-1:モンスター捕獲ゲームを作ろう
 ・確認問題5-2:マインスイーパを作ろう
アクセス修飾子とカプセル化入門|安全なクラス設計の基礎を学ぼう
クラスを設計するうえで、「アクセス修飾子」と「カプセル化」はとても重要な役割を持っています。
アクセス修飾子(public, private, protected)を使い分けることで、クラス内部のデータを外部から守り、安全で管理しやすいプログラムを書くことができます。
また、カプセル化の考え方を身につけることで、ゲッターやセッターを活用した柔軟なデータ管理や、不正な値の入力を防ぐバリデーションの実装にもつながります。
この記事を読むことで、「アクセス修飾子の違いが分からない」「カプセル化って何?」といった初心者の疑問をスッキリ解決し、より信頼性の高いPHPコードが書けるようになります。

アクセス修飾子とは何か?|データ保護のための基本概念
アクセス修飾子 とは、クラスのプロパティやメソッドへのアクセス可能な範囲を制御するためのキーワードです。
PHPには以下の3種類のアクセス修飾子があります。
- public(パブリック):クラスの外部や内部からアクセス可能。
 - protected(プロテクテッド):クラス自身とその子クラスからのみアクセス可能。
 - private(プライベート):クラス自身からのみアクセス可能。
 
これらのアクセス修飾子の使用例をコードで見てみましょう。
class Sample {
    public $publicVar;			// 外部からアクセス可能
    protected $protectedVar;	// 子クラス(※)からアクセス可能
    private $privateVar;		// 自クラス内からのみアクセス可能
}
$obj = new Sample();			// インスタンス生成
$obj->publicVar = 'OK';			// publicはアクセス可能
$obj->protectedVar = 'NG';		// エラー:protected変数へはアクセス不可
$obj->privateVar = 'NG';		// エラー:private変数へはアクセス不可なお、子クラスとは何か についてはLesson5-5で学習します。
カプセル化とは?|ゲッター・セッターで安全にデータ管理
カプセル化 とはクラス内のデータや処理を外部から直接操作できないようにし、安全にデータをやり取りする仕組みです。
先ほどのアクセス修飾子の使用例コードの場合、変数$privateVar は private によってカプセル化されていると言えます。
カプセル化することで外部から直接データを書き換えられないようになり、不正な値の代入や、予期しない動作を防ぐことができます。
しかし、完全に遮断してしまうと不便なので、外部から安全にデータをやりとりするための ゲッター と セッター を使用しましょう。
- ゲッター:カプセル化されたプロパティの値を取得するためのメソッド
 - セッター:カプセル化されたプロパティに値を設定するためのメソッド
 
以下は、ゲッターとセッターを使った具体例です。
class BankAccount {			// 銀行口座クラスを定義
    private $balance = 0;	// 口座残高をカプセル化
    private $value = 0;		// 入出金額をカプセル化
    // 残高を取得するゲッターメソッド
    public function getBalance() {	// getBalance()という名前のゲッターメソッドを定義
        return $this->balance;		// クラス内なので$balanceを参照できる
    }
  
    public function setValue($value) {	// setValue()という名前のセッターメソッドを定義
        $this->value = $value;			// クラス内なので$valueを参照できる
		if ($value != 0){
        	$this->balance += $value;	// クラス内なので$balanceを参照できる
    	}
    }
}
// インスタンス作成と操作例
$account = new BankAccount();	// インスタンス生成
$account->setValue(1000);		// セッターメソッドで入金
echo $account->getBalance();	// ゲッターメソッドで残高表示:1000
$account->setValue(-500);		// セッターメソッドで出金
echo $account->getBalance();	// ゲッターメソッドで残高表示:500この例では、残高はprivateで直接操作できないため、不正なアクセスや誤操作を防ぐことができます。
まとめ|アクセス修飾子とカプセル化を正しく使おう
ここまでで、アクセス修飾子の役割や種類、そしてカプセル化の基本的な考え方と、ゲッター・セッターを使った情報の管理方法について学びました。
これにより、クラス内部のデータを安全に守りつつ、必要なデータだけを外部とやりとりできる、実用的で堅牢なクラス設計ができるようになったはずです。
アクセス修飾子とカプセル化の考え方は、オブジェクト指向プログラミングの基礎となる重要な知識です。
ぜひ今回の内容を活かして、より質の高いコードを書けるよう、次のレッスンにもチャレンジしてみましょう!
演習問題|セッターとゲッターを使って安全なデータ管理を体験しよう

ユーザーの名前と年齢を管理するプログラムを作成しましょう。
このプログラムではアクセス修飾子を使用してデータを保護し、カプセル化によりデータへのアクセスを安全に制御します。
具体的にはゲッターとセッターを用いて名前と年齢の設定や取得を行い、無効なデータが設定されないようにバリデーションを組み込みます。
最後にユーザー情報を表示し、年齢を変更して再度情報を表示する機能を実装します。
この演習の要件
以下の要件に従ってコードを完成させてください。
- クラス User を作成すること。
 - クラス内に以下のprivateプロパティを定義すること:
- 名前($name):文字列型
 - 年齢($age):整数型
 
 - コンストラクタを定義し、オブジェクト作成時に名前と年齢を初期化できるようにすること。
 - 以下のゲッターとセッターを実装すること:
getName(): 名前を取得する。setName($name): 名前を設定する。ただし、空文字は許可しない。getAge(): 年齢を取得する。setAge($age): 年齢を設定する。ただし、0以上の数値のみ許可する。
 - ユーザー情報を表示する関数 
displayInfo()を作成すること。 - 例外処理を実装し、無効なデータが入力された場合はエラーメッセージを表示すること。
 
ただし、以下のような実行結果となること。
名前: 太郎 年齢: 25 年齢を更新しました。 名前: 太郎 年齢: 30
解き方のヒント
1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。
- ヒント1【コードの構成を見る】
 - 
正解のコードは上から順に以下のような構成となっています。
(※下記の□はコード内のインデントを表しています)1:PHPの開始タグを宣言
2:Userクラスを宣言
□ privateスコープの文字列型プロパティ$nameを定義
□ privateスコープの整数型プロパティ$ageを定義
□ コンストラクタを宣言(名前と年齢を初期化する)
□ □ setNameメソッドで名前を設定
□ □ setAgeメソッドで年齢を設定
□ getNameメソッドを宣言し、プロパティ$nameの値を返す
□ setNameメソッドを宣言し、名前のバリデーションと設定を行う
□ □ 名前が空欄の場合は例外をスロー
□ getAgeメソッドを宣言し、プロパティ$ageの値を返す
□ setAgeメソッドを宣言し、年齢のバリデーションと設定を行う
□ □ 年齢が0未満の場合は例外をスロー
□ displayInfoメソッドを宣言し、ユーザー情報を表示
3:tryブロックを開始
□ Userクラスのインスタンス$userを作成(名前「太郎」、年齢25で初期化)
□ $userオブジェクトのdisplayInfoメソッドを呼び出し、情報を表示
□ setAgeメソッドを使用して年齢を30に更新
□ 「年齢を更新しました。」と出力
□ 更新後の情報を再度displayInfoメソッドで表示
4:catchブロックを宣言し、例外発生時の処理を定義
□ 例外メッセージを「エラー:」とともに出力 
- ヒント2【穴埋め問題にする】
 - 
以下のコードをコピーし、コメントに従ってコードを完成させて下さい。
<?php // ユーザー情報を管理するクラス class User { // プロパティの宣言(privateでカプセル化) /* 【穴埋め問題1】 ここでユーザー名と年齢を格納するprivateスコープのプロパティを2つ定義してください。 名前は文字列型、年齢は整数型とします。 また、このプロパティはクラス外から直接アクセスできないようにしてください。 */ // コンストラクタ(初期化処理) public function __construct(string $name, int $age) { /* 【穴埋め問題2】 ここでコンストラクタを実装し、名前と年齢のバリデーションを行うメソッドを呼び出して初期化してください。 */ } // 名前を取得するゲッター /* 【穴埋め問題3】 ここで名前を取得するゲッターメソッドを定義してください。 このメソッドは名前を文字列型で返す必要があります。 */ // 名前を設定するセッター(バリデーション付き) public function setName(string $name): void { /* 【穴埋め問題4】 名前が空欄でないことを確認し、バリデーションに失敗した場合は例外をスローしてください。 バリデーションを通過した場合はプロパティに値を設定してください。 */ } // 年齢を取得するゲッター /* 【穴埋め問題5】 ここで年齢を取得するゲッターメソッドを定義してください。 このメソッドは年齢を整数型で返す必要があります。 */ // 年齢を設定するセッター(バリデーション付き) public function setAge(int $age): void { /* 【穴埋め問題6】 年齢が0以上であることを確認し、バリデーションに失敗した場合は例外をスローしてください。 バリデーションを通過した場合はプロパティに値を設定してください。 */ } // ユーザー情報を表示する関数 public function displayInfo(): void { echo "名前: " . $this->getName() . PHP_EOL; echo "年齢: " . $this->getAge() . PHP_EOL; } } // クラスの使用例 try { /* 【穴埋め問題7】 ここでUserクラスのインスタンスを作成し、名前「太郎」と年齢25を設定してください。 また、displayInfoメソッドを呼び出して初期状態の情報を表示してください。 */ /* 【穴埋め問題8】 年齢を30に更新し、更新メッセージを表示した後、再度displayInfoメソッドを呼び出して最新の情報を表示してください。 */ } catch (Exception $e) { echo "エラー: " . $e->getMessage() . PHP_EOL; } 
このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。
演習問題の答え合わせ
この問題の正解コードとその解説は以下の通りです。
クリックして開いて確認してください。
- 正解コード
 - 
<?php // ユーザー情報を管理するクラス class User { // プロパティの宣言(privateでカプセル化) private string $name; // ユーザー名(文字列) private int $age; // 年齢(整数) // コンストラクタ(初期化処理) public function __construct(string $name, int $age) { // 名前と年齢を設定(初期化時にバリデーションを適用) $this->setName($name); $this->setAge($age); } // 名前を取得するゲッター public function getName(): string { return $this->name; } // 名前を設定するセッター(バリデーション付き) public function setName(string $name): void { // 名前が空でないことを確認 if (trim($name) === '') { throw new Exception('名前は空欄にできません。'); } $this->name = $name; } // 年齢を取得するゲッター public function getAge(): int { return $this->age; } // 年齢を設定するセッター(バリデーション付き) public function setAge(int $age): void { // 年齢が0以上であることを確認 if ($age < 0) { throw new Exception('年齢は0以上である必要があります。'); } $this->age = $age; } // ユーザー情報を表示する関数 public function displayInfo(): void { echo "名前: " . $this->getName() . PHP_EOL; echo "年齢: " . $this->getAge() . PHP_EOL; } } // クラスの使用例 try { // ユーザーオブジェクトを作成 $user = new User('太郎', 25); // ユーザー情報の表示 $user->displayInfo(); // 年齢を変更 $user->setAge(30); echo "年齢を更新しました。" . PHP_EOL; // 更新後のユーザー情報の表示 $user->displayInfo(); } catch (Exception $e) { // エラーメッセージを表示 echo "エラー: " . $e->getMessage() . PHP_EOL; } 
- 正解コードの解説
 - 
コードをブロックごとに分割して解説します。
クラス定義とプロパティの宣言
class User { private string $name; private int $age;- class User: クラスはオブジェクトを作成するための設計図です。このクラスはユーザー情報を管理します。
 - private: アクセス修飾子の1つで、このプロパティはクラスの外部から直接アクセスできません。これによりデータの不正操作を防ぎます。
 - $name, $age: ユーザー名と年齢を保持する変数です。それぞれ文字列と整数型として型指定されています。型指定によりデータの誤入力を防ぎます。
 
コンストラクタの定義
public function __construct(string $name, int $age) { $this->setName($name); $this->setAge($age); }- public: アクセス修飾子の1つで、この関数は外部から呼び出すことができます。
 - __construct: コンストラクタは、オブジェクトが作成されるときに自動的に実行されます。
 - $this: このキーワードはクラスの現在のインスタンスを指します。
$this->setName()はインスタンス内のsetNameメソッドを呼び出します。 
ゲッターとセッターの定義
public function getName(): string { return $this->name; } public function setName(string $name): void { if (trim($name) === '') { throw new Exception('名前は空欄にできません。'); } $this->name = $name; }- getName(): プロパティ 
$nameの値を外部から取得するための関数(ゲッター)。外部から直接$nameにアクセスできないため、代わりにこの関数を使用します。 - setName(): プロパティ 
$nameの値を設定するための関数(セッター)。バリデーション(データの検証)も行い、空文字を防ぎます。 - 例外処理 (throw new Exception): 無効なデータが入力された場合にエラーを発生させ、プログラムの不正動作を防ぎます。
 
ユーザー情報の表示関数
public function displayInfo(): void { echo "名前: " . $this->getName() . PHP_EOL; echo "年齢: " . $this->getAge() . PHP_EOL; }- displayInfo(): ユーザー情報を表示する関数です。
 - PHP_EOL: 改行を表す定数で、環境によらず改行を統一できます。
 
クラスの使用例
$user = new User('太郎', 25); $user->displayInfo(); $user->setAge(30); $user->displayInfo();- new User(‘太郎’, 25): クラス 
Userの新しいインスタンスを作成し、名前と年齢を初期化します。 - $user->displayInfo(): ユーザー情報を表示します。
 - $user->setAge(30): 年齢を更新します。この操作もバリデーションを通じて安全に行われます。
 
例外処理
} catch (Exception $e) { echo "エラー: " . $e->getMessage() . PHP_EOL; }- try-catchブロック: エラーが発生した場合にプログラムを停止させず、安全にエラーメッセージを表示します。
 - getMessage(): 例外メッセージの内容を取得します。
 
 


