メインコンテンツまでスキップ

PHPのクラス基本文法

第 1 章では、Order クラスの中身を細かく説明せずに読み進めました。 この章では、privateやpublic functionのようなクラスの文法を 1 つずつ理解していきます。

クラスとプロパティ​

クラスはclassキーワードで定義します。 クラスの中に書く変数を、プロパティと呼びます。

class Order
{
private array $items = [];
private string $customerEmail;
}

private array $items = [];は、$itemsという名前のプロパティを宣言しています。 arrayは型宣言で、このプロパティに配列以外の値を代入しようとするとエラーになります。 privateは可視性修飾子で、意味は後述します。

メソッド​

クラスの中に定義された関数を、メソッドと呼びます。 メソッドの中では、$thisという特殊な変数を使って、自分自身のプロパティやメソッドにアクセスできます。

class Order
{
private array $items = [];

public function addItem(string $name, int $price): void
{
$this->items[] = ['name' => $name, 'price' => $price];
}
}

$this->itemsは、このオブジェクト自身が持つ$itemsプロパティを指します。

可視性修飾子: public・protected・private​

プロパティやメソッドには、クラスの外からどこまでアクセスできるかを決める可視性修飾子を付けます。

  • public: どこからでもアクセスできる
  • protected: 自分自身のクラスと、それを継承したクラスからアクセスできる(継承は第 5 章で扱います)
  • private: 自分自身のクラスの中からしかアクセスできない
class Order
{
private array $items = [];

public function getItemCount(): int
{
return count($this->items);
}
}

$order = new Order();
$order->getItemCount(); // OK: publicメソッドなので呼び出せる
$order->items; // エラー: privateプロパティなのでクラスの外からアクセスできない

$itemsを private にすることで、クラスの外から直接書き換えられることを防いでいます。 この考え方は、第 3 章「カプセル化と情報隠蔽」で詳しく扱います。

コンストラクタ​

オブジェクトを作成するとき(newするとき)に自動的に呼ばれるメソッドを、コンストラクタと呼びます。 PHP では__constructという名前で定義します。

class Order
{
private string $customerEmail;

public function __construct(string $customerEmail)
{
$this->customerEmail = $customerEmail;
}
}

$order = new Order('taro@example.com');

new Order('taro@example.com')とすると、コンストラクタが呼ばれ、引数$customerEmailが$this->customerEmailに代入されます。

コンストラクタプロモーション​

コンストラクタでよく書くのが、引数を受け取って同じ名前のプロパティにそのまま代入する、というパターンです。 上の Order クラスのコンストラクタも、この形をしています。

PHP 8.0 では、この定型的な書き方を省略できるコンストラクタプロモーションが導入されました1。

❌ Before: プロパティ宣言と代入を別々に書く
class Order
{
private string $customerEmail;

public function __construct(string $customerEmail)
{
$this->customerEmail = $customerEmail;
}
}
✅ After: コンストラクタプロモーション
class Order
{
public function __construct(
private string $customerEmail,
) {
}
}

コンストラクタの引数にprivateのような可視性修飾子を付けると、PHP が自動的に同名のプロパティを宣言し、代入まで行います。 プロパティ宣言と代入の 2 箇所に分かれていた記述が、1 箇所にまとまります。

readonlyプロパティ​

PHP 8.1 では、初期化した後は値を変更できないreadonlyプロパティが導入されました2。

class Order
{
public function __construct(
public readonly string $customerEmail,
) {
}
}

$order = new Order('taro@example.com');
$order->customerEmail = 'jiro@example.com'; // エラー: readonlyプロパティは再代入できない

顧客のメールアドレスのように、一度作成したら変わらないはずの値に readonly を付けておくと、意図しない書き換えを PHP の言語機能として防げます。

enum​

決まった選択肢の中からしか値を取らないデータを表すために、PHP 8.1 ではenum(列挙型)が導入されました3。

enum OrderStatus
{
case Pending;
case Shipped;
case Delivered;
}

$status = OrderStatus::Pending;

文字列や整数のような値と組にしたいときは、backed enumを使います。

enum OrderStatus: string
{
case Pending = 'pending';
case Shipped = 'shipped';
case Delivered = 'delivered';
}

echo OrderStatus::Pending->value; // 'pending'

OrderStatus::Pendingという値は、'pending'という文字列や1という数値よりも、意図を明確に表せます。 文字列の typo によるバグも、PHP の型システムが検出します。

まとめ​

  • クラスの中の変数をプロパティ、関数をメソッドと呼ぶ
  • 可視性修飾子(public・protected・private)で、クラスの外からのアクセス範囲を制御する
  • コンストラクタ(__construct)は、オブジェクト生成時に呼ばれる
  • コンストラクタプロモーション(PHP 8.0)は、プロパティ宣言と代入を 1 箇所にまとめる短縮記法
  • readonly プロパティ(PHP 8.1)は、初期化後の再代入を防ぐ
  • enum(PHP 8.1)は、決まった選択肢しか取らない値を型として表現する

次に読む​

次章では、カプセル化と情報隠蔽を扱います。 public property の危険性や、ゲッター・セッターの要否をどう判断するかを見ていきます。

練習問題​

次のクラスをコンストラクタプロモーションとreadonlyプロパティを使って書き直してください
class Product
{
private string $name;
private int $price;

public function __construct(string $name, int $price)
{
$this->name = $name;
$this->price = $price;
}

public function getName(): string
{
return $this->name;
}

public function getPrice(): int
{
return $this->price;
}
}

解答例

class Product
{
public function __construct(
private readonly string $name,
private readonly int $price,
) {
}

public function getName(): string
{
return $this->name;
}

public function getPrice(): int
{
return $this->price;
}
}

コンストラクタプロモーションでプロパティ宣言と代入をまとめ、readonly を付けることで、$nameと$priceが生成後に変更されないことを保証しています。


Footnotes​

  1. 出典: Constructor Promotion(PHP 公式マニュアル)。PHP 8.0.0 で導入されました。 ↩

  2. 出典: Readonly properties(PHP 公式マニュアル)。PHP 8.1 で導入されました。 ↩

  3. 出典: Enumerations(PHP 公式マニュアル)。PHP 8.1 で導入されました。 ↩