PHPのコンストラクタとは何か、使い方や書き方について

採用はこちら

目次

PHPのコンストラクタとは

PHPのコンストラクタとは、クラスからオブジェクトを生成するときに、初期化処理を行うための特別なメソッドです。
PHPでは、__construct()という名前でコンストラクタを定義します。

たとえば、ユーザーを表すクラスを作成するとき、名前やメールアドレスなどの値をオブジェクト生成時に設定したい場合があります。
このような初期値の設定をまとめて行うのがコンストラクタの代表的な役割です。

コンストラクタを利用すると、オブジェクトを作成した直後から必要な値が設定された状態にできるため、オブジェクト指向プログラミングでは重要な仕組みの一つとなっています。

コンストラクタは__construct()で定義する

PHPでは、次のように__construct()メソッドをクラス内に定義します。

class User
{
    public function __construct()
    {
        echo 'Userオブジェクトが生成されました。';
    }
}

このクラスから、

$user = new User();

とオブジェクトを生成すると、__construct()が呼び出されます。

通常のメソッドであれば、

$user->methodName();

のように明示的に呼び出す必要があります。

一方、コンストラクタは、利用されるコンストラクタが存在する場合、基本的にnewによるオブジェクト生成時に呼び出されるのが特徴です。

PHPでコンストラクタを使う目的

コンストラクタは、単にオブジェクト生成時に何らかの処理を実行するためだけのものではありません。

主な用途は、オブジェクトを正しい状態で使い始められるように初期化することです。

プロパティの初期値を設定する

最も基本的な使い方が、プロパティの初期化です。

たとえば、ユーザー名を保持するクラスを考えてみましょう。

class User
{
    public string $name;

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

オブジェクトを生成するときに、次のように名前を渡します。

$user = new User('Tanaka');

echo $user->name;

実行結果は次のようになります。

Tanaka

new User('Tanaka')で渡したTanakaが、コンストラクタの$nameに渡されます。

そして、

$this->name = $name;

によって、オブジェクトのnameプロパティに値が保存されます。

必須となる値をオブジェクト生成時に渡せる

コンストラクタを使うと、そのオブジェクトを利用するために必要な値を生成時に要求できます。

たとえば、ユーザーに名前とメールアドレスが必須である場合は、次のように記述できます。

class User
{
    public string $name;
    public string $email;

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

オブジェクトを生成するときは、

$user = new User(
    'Tanaka',
    'tanaka@example.com'
);

のように指定します。

この設計では、必要な引数を渡さなければ正常にオブジェクトを生成できません。

そのため、必要なデータの設定漏れを防ぎやすくなります。

コンストラクタの基本的な書き方

PHPのコンストラクタは、次のような構造で記述するのが基本です。

class クラス名
{
    public function __construct(引数)
    {
        // 初期化処理
    }
}

実際のコードでは、次のようになります。

class Product
{
    public string $name;
    public int $price;

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

使用するときは、

$product = new Product('ノートPC', 100000);

とします。

コンストラクタには複数の引数を指定できる

通常の関数やメソッドと同様に、コンストラクタにも複数の引数を設定できます。

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

次のように値を渡します。

$product = new Product(
    'ノートPC',
    100000,
    'パソコン'
);

商品名、価格、カテゴリーなど、オブジェクトの生成に必要な値をまとめて指定できます。

デフォルト値も設定できる

コンストラクタの引数にはデフォルト値を設定することもできます。

class User
{
    public string $name;
    public string $role;

    public function __construct(
        string $name,
        string $role = 'user'
    ) {
        $this->name = $name;
        $this->role = $role;
    }
}

roleを省略して、

$user = new User('Tanaka');

とした場合、roleにはuserが設定されます。

一方、

$admin = new User('Suzuki', 'admin');

と指定すれば、adminが設定されます。

コンストラクタで使う$thisとは

PHPのコンストラクタを理解するうえで、$thisは非常に重要です。

$thisは、現在処理しているオブジェクト自身を表します。

$this->プロパティ名でプロパティへアクセスする

たとえば、次のコードを見てみましょう。

class User
{
    private string $name;

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

この中にある、

$this->name = $name;

では、左側と右側で意味が異なります。

$this->nameは、現在のオブジェクトが持っているnameプロパティです。

一方、$nameはコンストラクタの引数です。

つまり、

$this->name = $name;

は、コンストラクタに渡された値をオブジェクトのプロパティへ代入していることになります。

PHP 8.0以降のコンストラクタプロパティプロモーション

PHP 8.0以降では、コンストラクタプロパティプロモーションと呼ばれる機能を利用できます。

これを使うと、プロパティの宣言とコンストラクタ内での代入を簡潔に書けます。

従来の書き方

従来は、次のようにプロパティを宣言したうえで、コンストラクタ内で値を代入していました。

class User
{
    private string $name;
    private string $email;

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

コンストラクタプロパティプロモーションを使った書き方

PHP 8.0以降では、次のように記述できます。

class User
{
    public function __construct(
        private string $name,
        private string $email
    ) {
    }
}

これだけで、実質的にプロパティの宣言と初期値の設定をまとめて表現できます。

コード量を大幅に減らせるため、現在のPHP開発ではよく利用される書き方です。

コンストラクタでpublic・protected・privateを使う方法

コンストラクタにもアクセス修飾子を指定できます。

通常はpublicを使用しますが、設計によってはprotectedprivateを利用することもあります。

publicコンストラクタ

一般的なクラスでは、次のようにpublicで定義します。

class User
{
    public function __construct()
    {
    }
}

この場合、

$user = new User();

としてクラスの外部からオブジェクトを生成できます。

privateコンストラクタ

コンストラクタをprivateにすると、クラス外部から直接newできなくなります。

class User
{
    private function __construct()
    {
    }
}

この場合、

$user = new User();

のような生成はできません。

オブジェクトの生成方法を制限したい場合などに利用できます。

staticメソッドからオブジェクトを生成する方法

privateコンストラクタと組み合わせて、ファクトリーメソッドからオブジェクトを生成する設計もあります。

class User
{
    private function __construct(
        private string $name
    ) {
    }

    public static function create(string $name): self
    {
        return new self($name);
    }
}

利用するときは、

$user = User::create('Tanaka');

とします。

この方法を使うと、オブジェクト生成の処理をクラス側で制御できます。

継承したクラスでコンストラクタを使う方法

PHPでは、クラスを継承した場合のコンストラクタの動作にも注意する必要があります。

子クラスにコンストラクタがない場合

親クラスにコンストラクタがあり、子クラス側で独自のコンストラクタを定義していない場合は、親クラスから継承したコンストラクタを利用できます。

class User
{
    public function __construct()
    {
        echo 'User constructor';
    }
}

class AdminUser extends User
{
}

次のように、

$admin = new AdminUser();

とすると、親クラス側のコンストラクタが利用されます。

子クラスに独自のコンストラクタがある場合

子クラス側で独自のコンストラクタを定義した場合は、親クラスのコンストラクタが自動的に追加で実行されるわけではありません。

たとえば、

class User
{
    public function __construct()
    {
        echo 'User';
    }
}

class AdminUser extends User
{
    public function __construct()
    {
        echo 'AdminUser';
    }
}

の場合、AdminUserのコンストラクタが実行されます。

親クラスのコンストラクタも呼び出したい場合は、parent::__construct()を使います。

parent::__construct()の使い方

親クラスのコンストラクタを明示的に呼び出すには、

parent::__construct();

を記述します。

たとえば、

class User
{
    public function __construct(
        protected string $name
    ) {
    }
}

class AdminUser extends User
{
    public function __construct(
        string $name,
        private int $level
    ) {
        parent::__construct($name);
    }
}

とします。

生成するときは、

$admin = new AdminUser('Tanaka', 1);

とします。

このとき、AdminUserのコンストラクタから、

parent::__construct($name);

を通じてUserクラスのコンストラクタを呼び出しています。

コンストラクタで値を検証する方法

コンストラクタでは、オブジェクト生成時に渡された値を検証することもできます。

不正な値を持つオブジェクトの生成を防ぐ

たとえば、商品の価格は0円以上でなければならないとします。

class Product
{
    public function __construct(
        private string $name,
        private int $price
    ) {
        if ($price < 0) {
            throw new InvalidArgumentException(
                '価格は0以上で指定してください。'
            );
        }
    }
}

この場合、

$product = new Product('商品A', -100);

とすると例外が発生します。

これによって、マイナス価格の商品オブジェクトが作成されることを防げます。

コンストラクタは、単に値を保存するだけでなく、オブジェクトを正しい状態で生成するためにも利用できます。

コンストラクタから別のメソッドを呼び出す方法

コンストラクタ内から、同じクラスに定義された別のメソッドを呼び出すこともできます。

class User
{
    public function __construct()
    {
        $this->initialize();
    }

    private function initialize(): void
    {
        echo '初期化しました。';
    }
}

new User()によってコンストラクタが呼び出されると、そこからinitialize()が実行されます。

ただし、コンストラクタに大量の処理を詰め込みすぎるとコードの流れが分かりにくくなるため、必要に応じてメソッドへ処理を分割することが重要です。

コンストラクタとDIの関係

実務のPHP開発では、コンストラクタはDIにもよく利用されます。

DIとはDependency Injectionの略で、日本語では依存性注入と呼ばれます。

コンストラクタインジェクションの例

たとえば、メール送信を担当するクラスがあるとします。

class Mailer
{
    public function send(): void
    {
        echo 'メールを送信しました。';
    }
}

このMailerUserServiceで利用する場合、次のようにコンストラクタから受け取れます。

class UserService
{
    public function __construct(
        private Mailer $mailer
    ) {
    }

    public function register(): void
    {
        // ユーザー登録処理

        $this->mailer->send();
    }
}

利用するときは、

$mailer = new Mailer();

$userService = new UserService($mailer);

とします。

このように、必要なオブジェクトをコンストラクタから受け取る方式をコンストラクタインジェクションと呼びます。

LaravelやSymfonyなどのPHPフレームワークを利用する場合にも、重要になる考え方です。

コンストラクタを使うメリット

コンストラクタを適切に利用すると、クラスの設計を分かりやすくできます。

初期化処理をまとめられる

コンストラクタを使わない場合は、

$user = new User();

$user->name = 'Tanaka';
$user->email = 'tanaka@example.com';

のように、オブジェクトを生成したあとで一つずつ値を設定することがあります。

一方、コンストラクタを使えば、

$user = new User(
    'Tanaka',
    'tanaka@example.com'
);

のように、生成と同時に初期化できます。

設定漏れを防ぎやすい

オブジェクトの利用に必要な値をコンストラクタ引数にしておけば、必要な値の設定漏れを防ぎやすくなります。

たとえば、

public function __construct(
    string $name,
    string $email
) {
}

と定義されている場合、

new User();

のように引数を渡さず生成することはできません。

オブジェクトが成立するために必要な値を明確にできる点も、コンストラクタの大きなメリットです。

オブジェクトを正しい状態で生成しやすい

コンストラクタで入力値の検証を行えば、不正な状態のオブジェクトが生成されるのを防ぎやすくなります。

そのため、クラスの内部状態を安全に保つという意味でもコンストラクタは重要です。

コンストラクタを書くときの注意点

コンストラクタは便利ですが、何でも処理を記述すればよいわけではありません。

設計しやすいコードにするためには、いくつか注意点があります。

重い処理を詰め込みすぎない

PHPの仕様上、コンストラクタ内でデータベース処理やファイル操作、外部APIとの通信などを行うこと自体は禁止されていません。

しかし、

new User();

しただけで時間のかかる処理や大きな副作用が発生すると、クラスの動作が分かりにくくなることがあります。

そのため、コンストラクタでは主に、

  • プロパティの初期化
  • 必要な依存オブジェクトの受け取り
  • 初期値の検証
  • オブジェクト成立に必要な最低限の処理

などを行う設計がよく使われます。

引数を増やしすぎない

コンストラクタには多くの引数を設定できますが、数が増えすぎるとコードが読みづらくなります。

たとえば、

public function __construct(
    string $name,
    string $email,
    string $address,
    string $phone,
    string $nickname,
    string $description
) {
}

のように大量の値が必要になると、オブジェクト生成時のコードも複雑になります。

その場合は、本当に生成時にすべて必要なのかを検討したり、値オブジェクトなど別の設計を検討したりするとよいでしょう。

PHP 8.2以降では動的プロパティに注意する

現在のPHPでは、プロパティの扱いについても注意が必要です。

PHP 8.2では、一般的なユーザー定義クラスに対して動的プロパティを新しく作成する方法が非推奨になっています。

そのため、

class User
{
    public function __construct(string $name)
    {
        $this->name = $name;
    }
}

のように、プロパティを宣言せずに値を代入する書き方は避けたほうがよいでしょう。

次のように明示的に宣言します。

class User
{
    private string $name;

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

または、PHP 8.0以降であれば、

class User
{
    public function __construct(
        private string $name
    ) {
    }
}

とコンストラクタプロパティプロモーションを利用できます。

古いPHPのコンストラクタとの違い

古いPHPでは、クラス名と同じ名前のメソッドをコンストラクタとして扱う形式が存在しました。

たとえば、

class User
{
    public function User()
    {
    }
}

といった書き方です。

しかし、現在のPHPを前提とする場合、この形式をコンストラクタとして使用するべきではありません。

現在は、

public function __construct()
{
}

という書き方を使用します。

古いPHPのコードを読む際には、この違いを知っておくと役立ちます。

PHPのコンストラクタとデストラクタの違い

PHPには、コンストラクタと対になる仕組みとしてデストラクタもあります。

コンストラクタはオブジェクトの生成時に使う

コンストラクタは、

__construct()

で定義します。

主にオブジェクト生成時の初期化処理に利用します。

class Sample
{
    public function __construct()
    {
        echo '生成しました。';
    }
}

デストラクタはオブジェクトの破棄時に使う

デストラクタは、

__destruct()

で定義します。

class Sample
{
    public function __destruct()
    {
        echo '破棄されます。';
    }
}

大まかに整理すると、次のようになります。

メソッド主なタイミング主な用途
__construct()オブジェクト生成時初期化
__destruct()オブジェクト破棄時など終了処理

コンストラクタとデストラクタは名前が似ていますが、役割は異なります。

PHPのコンストラクタの基本形

PHPのコンストラクタを初めて学ぶ場合は、まず次の形を覚えておくとよいでしょう。

class User
{
    private string $name;
    private string $email;

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

オブジェクトを生成するときは、

$user = new User(
    'Tanaka',
    'tanaka@example.com'
);

とします。

PHP 8.0以降であれば、さらに簡潔に、

class User
{
    public function __construct(
        private string $name,
        private string $email
    ) {
    }
}

と書くこともできます。

PHPのコンストラクタについて覚えておきたいポイント

PHPのコンストラクタは、オブジェクト生成時の初期化を担当する重要な仕組みです。

基本的には__construct()で定義し、プロパティへの初期値の設定や、必要な依存オブジェクトの受け取り、初期値の検証などに利用します。

特に覚えておきたいポイントは次のとおりです。

  • コンストラクタは__construct()で定義する
  • オブジェクト生成時の初期化に利用する
  • 引数からプロパティへ値を設定できる
  • $thisは現在のオブジェクト自身を表す
  • 引数には型やデフォルト値を設定できる
  • PHP 8.0以降ではコンストラクタプロパティプロモーションを使える
  • 親クラスのコンストラクタを明示的に呼ぶ場合はparent::__construct()を使う
  • privateコンストラクタによってオブジェクトの生成方法を制御できる
  • コンストラクタインジェクションによるDIにも利用される
  • 重い処理を入れることは可能だが、設計上は初期化に必要な処理へ絞ることが多い

PHPのコンストラクタを理解すると、単にクラスを作成できるだけでなく、オブジェクトを安全で分かりやすい状態に保つ設計がしやすくなります。

また、LaravelやSymfonyなどのPHPフレームワークで使われるDIやサービスクラスの理解にもつながるため、PHPのオブジェクト指向を学ぶうえで押さえておきたい重要な機能です。

以上、PHPのコンストラクタとは何か、使い方や書き方についてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次