基礎

PHPのコンストラクタ(__construct)|オブジェクト初期化の基本

PHPのコンストラクタは、new でインスタンスを生成したときに自動的に呼び出される特殊なメソッドです。__construct() という名前で定義し、プロパティの初期値設定やリソースの準備など、オブジェクトの初期化処理を行います。

コンストラクタはオブジェクト指向プログラミングの基本要素で、オブジェクトが常に有効な状態で生成されることを保証する役割を持ちます。

基本的な使い方

PHP
<?php
class User {
    public string $name;
    public int $age;

    public function __construct(string $name, int $age) {
        echo "コンストラクタが呼ばれました\n";
        $this->name = $name;
        $this->age = $age;
    }

    public function greet(): string {
        return "私は{$this->name}、{$this->age}歳です。";
    }
}

$user = new User("田中", 30);
echo $user->greet() . "\n";
実行結果
コンストラクタが呼ばれました
私は田中、30歳です。

new User("田中", 30) と書くだけで、__construct() が自動的に呼び出され、プロパティが初期化されます。

コンストラクタプロモーション(PHP 8.0+)

PHP 8.0以降では、コンストラクタの引数にアクセス修飾子を付けることで、プロパティの宣言と初期化を一度に行えます。

PHP
<?php
// 従来の書き方
class ProductOld {
    private string $name;
    private int $price;

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

// PHP 8.0+ コンストラクタプロモーション
class Product {
    public function __construct(
        private string $name,
        private int $price,
        private int $stock = 0
    ) {
        // 追加の初期化処理があればここに書く
    }

    public function getInfo(): string {
        return "{$this->name}: {$this->price}円(在庫: {$this->stock})";
    }
}

$p = new Product("PHP入門書", 2980, 50);
echo $p->getInfo() . "\n";

$p2 = new Product("ノート", 150);
echo $p2->getInfo() . "\n";
実行結果
PHP入門書: 2980円(在庫: 50)
ノート: 150円(在庫: 0)

バリデーション付きコンストラクタ

PHP
<?php
class Age {
    private int $value;

    public function __construct(int $value) {
        if ($value < 0 || $value > 150) {
            throw new InvalidArgumentException("年齢は0〜150の範囲で指定してください(入力値: {$value})");
        }
        $this->value = $value;
    }

    public function getValue(): int {
        return $this->value;
    }
}

try {
    $age1 = new Age(25);
    echo "年齢: {$age1->getValue()}歳\n";

    $age2 = new Age(-5);
} catch (InvalidArgumentException $e) {
    echo "エラー: {$e->getMessage()}\n";
}
実行結果
年齢: 25歳
エラー: 年齢は0〜150の範囲で指定してください(入力値: -5)

継承時のコンストラクタ

PHP
<?php
class Animal {
    public function __construct(
        protected string $name,
        protected string $type
    ) {
        echo "Animal::__construct({$name})\n";
    }
}

class Dog extends Animal {
    public function __construct(string $name, private string $breed) {
        // 親のコンストラクタを呼ぶ
        parent::__construct($name, "犬");
        echo "Dog::__construct({$name}, {$breed})\n";
    }

    public function getInfo(): string {
        return "{$this->name}({$this->type}・{$this->breed})";
    }
}

$dog = new Dog("ポチ", "柴犬");
echo $dog->getInfo() . "\n";
実行結果
Animal::__construct(ポチ)
Dog::__construct(ポチ, 柴犬)
ポチ(犬・柴犬)

実用的な例

PHP
<?php
class DatabaseConnection {
    private string $dsn;

    public function __construct(
        string $host = "localhost",
        int $port = 3306,
        string $dbName = "app",
        string $charset = "utf8mb4"
    ) {
        $this->dsn = "mysql:host={$host};port={$port};dbname={$dbName};charset={$charset}";
    }

    public function getDsn(): string {
        return $this->dsn;
    }
}

$db1 = new DatabaseConnection();
echo $db1->getDsn() . "\n";

$db2 = new DatabaseConnection("db.example.com", 3307, "production");
echo $db2->getDsn() . "\n";
実行結果
mysql:host=localhost;port=3306;dbname=app;charset=utf8mb4
mysql:host=db.example.com;port=3307;dbname=production;charset=utf8mb4
ポイント

子クラスが独自のコンストラクタを定義しない場合、親クラスのコンストラクタが自動的に継承されます。独自に定義する場合は parent::__construct() を忘れずに呼びましょう。呼ばないと親クラスの初期化が行われません。

注意

コンストラクタ内で重い処理(ファイル読み込み、外部API呼び出しなど)を行うと、オブジェクト生成のたびに時間がかかります。重い初期化は遅延実行(必要になったタイミングで実行)するか、ファクトリメソッドに分離することを検討しましょう。

まとめ

  • __construct()new 時に自動的に呼ばれる初期化メソッド
  • PHP 8.0のコンストラクタプロモーションで宣言と初期化を簡略化できる
  • バリデーションを入れることで、不正な状態のオブジェクト生成を防げる
  • 子クラスでは parent::__construct() で親の初期化を忘れずに呼ぶ
  • 重い処理はコンストラクタに入れず、遅延実行を検討する