ここでは、PHP でプロパティを実装するサンプルスクリプトを掲載しています。4つのマジックメソッド ( __set __get __isset __unset ) を利用しています。
スポンサーリンク
__set, __get, __isset, __unset マジックメソッドでプロパティ
PHP では、上記のマジックメソッドを使用することにより、定義(宣言)されていないメソッド(プロパティ)を、存在しているようにふるまう仕組みがあります。PHP ではこの機構のことをプロパティのオーバーロードと呼びます。 (多言語のように同一名でパラメータの異なる複数のメソッドを定義することを指すわけではありません)
次のスクリプトでは、存在しないメソッド(属性)に対して値の設定 ( __set ) と取得 (__get) を行っています。プロパティアクセスのように振舞います。
※ なお、下記は、オーバーロードを抜粋しただけなので 詳細はリンクから確認ください。
class PropertyOverload
{
/**
* オーバーロードされるデータの場所
*/
private $_data = array();
/**
* 定義されていない属性へ値が設定される場合に呼び出される
*/
public function __set($name, $value)
{
$this->_data[$name] = $value;
}
/**
* 定義されていない属性から値を取得される場合に呼び出される
*/
public function __get($name)
{
if(isset($this->_data[$name])) {
return $this->_data[$name];
}
return null;
}
/**
* 未定義属性に対する isset の呼び出しの場合に呼び出される。
* PHP 5.1.0 以降で使用可能
*/
public function __isset($name)
{
return isset($this->_data[$name]);
}
/**
* 未定義属性に対する unset の呼び出しの場合に呼び出される。
* PHP 5.1.0 以降で使用可能
*/
public function __unset($name)
{
unset($this->_data[$name]);
}
}
$prop = new PropertyOverload();
/*
* クラスで宣言されていない属性から値を取得
*/
var_dump(isset($prop->intval)); // __isset マジックメソッドが呼び出される
var_dump($prop->intval);
/*
* クラスで宣言されていない属性に値を設定して、その結果を確認する
*/
$prop->intval = 1;
var_dump(isset($prop->intval)); // __isset マジックメソッドが呼び出される
var_dump($prop->intval);
/*
* __unset マジックメソッドを呼出しプロパティ値の解除とその確認
*/
unset($prop->intval);
var_dump(isset($prop->intval));
// 出力
// -----------------------------------
// bool(false)
// NULL
//
// bool(true)
// int(1)
//
// bool(false)
また、個々のセッターとゲッターを用意して、個々のチェックを行ったりすることもできます。基準を決めて使い分けを行えばよいでしょう。
class LikeProperty
{
// プロパティ値を格納する器
private $_intval = 0;
// 疑似 getter
public function getIntval()
{
return $this->_intval;
}
// 疑似 setter
public function setIntval($intval)
{
$this->_intval = $intval;
}
}
// インスタンス生成
$prop = new LikeProperty();
// 疑似 getter
echo $prop->getIntval() . "\n";
// 疑似 setter
$prop->setIntval(4);
echo $prop->getIntval() . "\n";
// 出力
// 0
// 4

__getや__setで想定しない$nameがわたってくる原因が単純なパンチミスであることを想定すると
debug_backtrace();で取得した呼び出し元のファイル名と行番号も設定してthrowしたほうがミスパンチした箇所がすぐにわかって便利かも。