記事内にはプロモーションが含まれています

【PHP】クラス変数とプロパティの基礎!static・private・初期化を徹底解説

【PHP】クラス変数とプロパティの基礎!static・private・初期化を徹底解説 PHP

PHPでオブジェクト指向プログラミングを行う際、必ず理解しておかなければならないのが「クラス内で扱う変数」の仕組みです。

しかし、「クラス変数」「メンバ変数」「プロパティ」「インスタンス変数」など、似たような用語が多く、混乱してしまう方も多いのではないでしょうか。

特に「クラス変数」という言葉は、文脈によって「クラス固有の変数(static)」を指すこともあれば、単に「クラス内の変数全般」を指すこともあります。

この違いを理解せずにコードを書くと、予期せぬエラーやバグの原因となります。

この記事では、PHPにおけるクラス内の変数の扱いについて、用語の整理から具体的なコードの書き方、そしてPHP 8以降の最新仕様である「型宣言」や「動的プロパティの廃止」までをわかりやすく解説します。

【本記事の信頼性】
プロフィール
執筆者:マヒロ
  • 執筆者は元エンジニア
  • SES⇒大手の社内SE⇒独立
  • 現在はこじんまりとしたプログラミングスクールを運営
  • モットーは「利他の精神」

PHPにおける「クラス変数」とは?用語の整理と違い

PHPの公式ドキュメントでは、クラス内で定義される変数のことを「プロパティ(Property)」と呼びます。

一般的に「クラス変数」と呼ばれるものには、大きく分けて以下の2種類が存在します。
まずはこの違いを明確にしておきましょう。

インスタンスプロパティ(メンバ変数)

クラスから生成された「インスタンス(オブジェクト)」ごとに独立して持つ変数です。
通常、単に「プロパティ」や「メンバ変数」と言った場合はこちらを指します。

インスタンス化(new)するまで利用できず、インスタンスごとに異なる値を保持できます。

staticプロパティ(静的プロパティ・クラス変数)

クラスそのものに紐付く変数です。狭義の「クラス変数」はこちらを指します。
インスタンス化しなくても利用でき、すべてのインスタンスで同じ値を共有します。

static キーワードを付けて宣言します。

用語 宣言 アクセス方法 特徴
インスタンス変数 public $name; $obj->name インスタンスごとに値が別々
クラス変数 (static) public static $count; ClassName::$count 全インスタンスで値を共有

ここからは、それぞれの具体的な使い方を見ていきましょう。

インスタンス変数の宣言とアクセス方法

インスタンス変数は、クラスの中で関数(メソッド)の外側に宣言します。
オブジェクトごとのデータを保持するために使用される、最も基本的なプロパティです。

基本的な宣言と呼び出し(アロー演算子)

インスタンス変数を定義する際は、アクセス修飾子(public, private, protected)を明記することが推奨されています。

アクセスにはアロー演算子 -> を使用します。

<?php
class User {
    // インスタンス変数の宣言
    public $name;
    public $age;
}

// インスタンス化
$user1 = new User();
$user1->name = "田中"; // 値の代入
$user1->age = 25;

$user2 = new User();
$user2->name = "佐藤"; // user1とは別の値を保持できる
$user2->age = 30;

echo "User1: " . $user1->name . " (" . $user1->age . "歳)\n";
echo "User2: " . $user2->name . " (" . $user2->age . "歳)\n";
?>

実行結果は以下の通りです。

User1: 田中 (25歳)
User2: 佐藤 (30歳)

クラス内部からのアクセス($this)

クラス内部のメソッドから自身のインスタンス変数にアクセスする場合は、擬似変数 $this を使用します。

<?php
class User {
    public $name;

    public function introduce() {
        // $this->name で自身のプロパティにアクセス
        echo "私の名前は" . $this->name . "です。\n";
    }
}

$user = new User();
$user->name = "鈴木";
$user->introduce();
?>

注意点として、$this->name のようにプロパティ名に $ は付けません($this->$name と書くと別の意味になります)。

クラス変数(staticプロパティ)の宣言とアクセス方法

すべてのインスタンスで共通の値を持ちたい場合や、ユーティリティ的な値を保持したい場合は、static キーワードを使ってクラス変数を定義します。

static変数の宣言とスコープ定義演算子(::)

static変数はインスタンス化せずに、クラス名から直接アクセスします。
この時、アロー演算子ではなく、スコープ定義演算子(ダブルコロン ::)を使用します。

<?php
class Counter {
    // staticプロパティ(クラス変数)
    public static $count = 0;

    public function __construct() {
        // コンストラクタが呼ばれるたびにカウントアップ
        // クラス内部からは self::$変数名 でアクセス
        self::$count++;
    }
}

echo "初期値: " . Counter::$count . "\n";

new Counter();
new Counter();
new Counter();

echo "生成後: " . Counter::$count . "\n";
?>

実行結果は以下の通りです。

初期値: 0
生成後: 3

インスタンスを3回生成した結果、共通の変数である $count が共有されて加算されていることがわかります。

クラス内部からアクセスする場合は self::$count と記述します。

プロパティの初期化と型宣言(PHP 7.4 / 8.0以降)

近年のPHP開発では、プロパティに対して「初期値」と「型」を明確に定義することがスタンダードになっています。

これにより、バグの少ない堅牢なコードを書くことができます。

プロパティの型宣言(Type Hinting)

PHP 7.4からプロパティに型を指定できるようになりました。

指定した型以外の値を代入しようとするとエラーが発生するため、データの整合性を保ちやすくなります。

<?php
class Product {
    // 型宣言付きのプロパティ
    public string $name;
    public int $price;
    public ?string $description = null; // nullを許容する場合は?を付ける

    // 配列の型指定も可能
    public array $tags = [];
}

$item = new Product();
$item->name = "ノートPC";
$item->price = 100000;
// $item->price = "十万円"; // これはエラー(TypeError)になる
?>

コンストラクタでのプロパティ昇格機能

PHP 8.0からは、コンストラクタの引数でプロパティの宣言と初期化を同時に行える「Constructor Property Promotion(プロパティの昇格)」機能が導入されました。

これにより、コード記述量が大幅に削減できます。

従来の書き方

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

PHP 8.0以降の書き方

class User {
    // アクセス修飾子を引数につけるだけでプロパティ定義になる
    public function __construct(
        public string $name,
        public int $age = 20 // 初期値も指定可能
    ) {}
}

$user = new User("山田");
echo $user->name; // 山田

アクセス修飾子(public, private, protected)の使い分け

クラス変数を適切に管理するためには、どこからアクセスできるかを制限する「アクセス修飾子」の設定が重要です。

これをカプセル化と呼びます。

3つの修飾子の違い

  • public:どこからでもアクセス可能。
  • protected:そのクラス自身と、継承したクラス(子クラス)からのみアクセス可能。
  • private:そのクラス自身からのみアクセス可能。外部や子クラスからは見えない。
<?php
class BankAccount {
    public string $bankName = "PHP銀行"; // 公開情報
    private int $balance = 0; // 残高は外部から直接いじらせない

    public function deposit(int $amount) {
        if ($amount > 0) {
            $this->balance += $amount;
            echo "{$amount}円預け入れました。\n";
        }
    }

    public function getBalance() {
        return $this->balance;
    }
}

$account = new BankAccount();
echo $account->bankName . "\n"; // OK

// $account->balance = 1000000; // Fatal Error: privateプロパティにはアクセスできない

$account->deposit(5000);
echo "残高: " . $account->getBalance() . "円\n";
?>

重要なデータは private に設定し、操作用のメソッド(ゲッターやセッター)を通してアクセスさせるのがオブジェクト指向の基本です。

【注意】動的プロパティの廃止について(PHP 8.2以降)

これまでPHPでは、クラス内で宣言していないプロパティに対して値を代入すると、自動的にそのプロパティが生成される「動的プロパティ」という機能がありました。

しかし、PHP 8.2以降、この動的プロパティの作成は非推奨(Deprecated)となりました。

動的プロパティの例(非推奨)

<?php
class Sample {}

$obj = new Sample();
// クラス定義にないプロパティへの代入
$obj->unknownProperty = "test"; // PHP 8.2以降ではWarningが出る
?>

スペルミスによる意図しないプロパティ生成を防ぐため、クラスで使用する変数は必ずクラス定義内で明示的に宣言するようにしましょう。

もしどうしても動的なプロパティが必要な場合は、#[AllowDynamicProperties] アトリビュートを使用するか、stdClass を利用します。

PHPのスキルを活かして年収を上げる方法

以上、PHPの「クラス変数」について解説してきました。

なお、PHPのスキルがある場合には、「転職して年収をアップさせる」「副業で稼ぐ」といった方法を検討するのがおすすめです。

PHPエンジニアの需要は非常に高く求人数・案件数も多いため、転職によって数十万円の年収アップはザラで、100万円以上年収が上がることも珍しくありません。

なお、転職によって年収を上げたい場合は、エンジニア専門の転職エージェントサービスを利用するのが最適です。

今すぐ転職する気がなくとも、とりあえず転職エージェントに無料登録しておくだけで、スカウトが届いたり、思わぬ好待遇の求人情報が送られてきたりするというメリットがあります。

併せて、副業案件を獲得できるエージェントにも登録しておくと、空いている時間を活かして稼げるようなPHPの案件を探しやすくなります。

転職エージェントも副業エージェントも、登録・利用は完全無料なので、どんな求人や副業案件があるのか気になる方は、気軽に利用してみるとよいでしょう。