🦠

PHPでプロパティを動的にセットする(MVC学習)

2022/08/11に公開

やりたいこと

Laravelのモデルインスタンスでは、各カラムの値をプロパティとして取得できる。しかし、クラス内にはテーブル名のプロパティは定義されていない。クラスの定義ファイルで書かれていないプロパティを作る仕組みを真似して、Modelファイルにプロパティを手入力する必要がないコードを作りたい。

動的プロパティ

存在しないプロパティに無理やり値を入れる方法。

class Test {
	private $prop1;
}

$test = new Test();
$test->prop2 = 'aaaaa'; //PHP9.0より前はセットできる

いきなり解決策では?と思ったが、PHP9.0以降で廃止されることが決まっている。

https://column.prime-strategy.co.jp/archives/column_5003#outline__3

stdClassを継承させれば9.0以降もエラーにならないが、他に継承させたいクラスがあると思うし、親クラスが全然関係ないクラスになるとわかりにくいコードになりそう。あまり現実的ではない。

マジックメソッドを使う

PHPでは、マジックメソッド__set()__get()を使うのがオーソドックスらしい。処理の流れとしては、インスタンスから列名が参照されたとき、dbを参照して動的にプロパティを作るというもの。

__set() は、 アクセス不能(protected または private)または存在しないプロパティへデータを書き込む際に実行されます。

__get() は、 アクセス不能(protected または private)または存在しないプロパティからデータを読み込む際に使用します。

https://www.php.net/manual/ja/language.oop5.overloading.php#object.set

<?php 
class Model {
    private $columns = []; //カラム

    public function __set($column, $value)
    {
        $this->columns[$column] = $value;
    }

    public function __get($column)
    {
        if(array_key_exists($column, $this->columns)) {
            return $this->columns[$column];
        } else {
            return null;
        }
    }
}

存在しないカラムにアクセスした時の処理もつけるとLaravelのロジックに近づけられそう。


  if(カラムがDBに存在したら) {
      $this->columns[$column] = $value;
  } else {
      return null;
  }

DBを参照する処理も追加したい。

追記2022/08/12
Laravelのヘルパー関数にも同じような仕組みが使われていたような気がする...(たしかcallStatic()だったはず)

参考記事

https://qiita.com/rana_kualu/items/53012c8f84e0f92220c1

https://atmarkit.itmedia.co.jp/ait/articles/1804/05/news008.html

https://atmarkit.itmedia.co.jp/ait/articles/1804/05/news008.html

Discussion