読めるけど書けない
読めるけど書けない修飾子としてPHPには「niigata新潟アクセス修飾子」という@supper_rtiさんが作ってくれたパッチが存在します。
ネタと言えばネタだけど、とても素敵だし、本家にも実装してほしい機能の一つだったりもしますw
でもパッチ当てるのは実際面倒だし・・・そもそもそういう事が出来ない環境だけど、niigataアクセス修飾子が欲しくなるときは多々あるかと思います。
__get()使えば普通に実装できるって話も聞いてたので、実際に実装してみました。
速度的にはあれだけど、まあ遊びとして使う分にはありかと思いますw
<?php
abstract class Lemon {
protected $__isNigata2Properties;
protected $__isFinalProperties;
public function __construct() {
$this->__isNigata2Properties = array();
$this->__isFinalProperties = array();
$refectionClass = new ReflectionClass($this);
foreach ($refectionClass->getProperties() as $property) {
if ($property->getDocComment() === false) {
continue;
}
if ($property->isPublic()) {
continue;
}
foreach (explode("\n",$property->getDocComment()) as $value) {
$value = str_replace(array("\t", "*", "\n", " "), "", $value);
if ($this->__isNiigataAccess($value)) {
$this->__isNigata2Properties[$property->getName()] = true;
$this->__isFinalProperties[$property->getName()] = $this->__isFinalAccess($value);
break;
}
}
}
}
/**
* GETマジックメソッド
* @param string $name
* @return string
*/
public function __get($name) {
if (isset($this->__isNigata2Properties[$name])) {
$reflection = new ReflectionProperty($this,$name);
$reflection->setAccessible(true);
if ($this->__isFinalProperties[$name]) {
$refectionClass = new ReflectionClass($this);
$defaultProperties = $refectionClass->getDefaultProperties();
return $defaultProperties[$name];
} else {
return $reflection->getValue($this);
}
} else {
return parent::__get($name);
}
}
/**
* 檸檬かどうかのチェックを行う
* @param string $value
* @return boolean
*/
protected function __isNiigataAccess($value) {
return (strpos($value,"@access") !== false && strpos($value,"lemon"));
}
protected function __isFinalAccess($value) {
return (strpos($value,"@access") !== false && strpos($value,"final"));
}
}
// 以下テスト
// 変数のプロパティに対して「@access」のあとに「lemon」、「檸檬」、「れもん」とか
// つければプライベートな変数にアクセスできる
class Hoge extends Lemon {
/**
* @access lemon
*/
private $hoge = "れもん";
/**
* @access final lemon
*/
private $hoge2 = "イエロー";
public function change() {
$this->hoge = "レモン汁";
}
public function change2() {
$this->hoge2 = "ぶるー";
}
public function check() {
var_dump($this->hoge2);
}
}
$hoge = new Hoge();
var_dump($hoge->hoge);
$hoge->change();
var_dump($hoge->hoge);
var_dump("----");
var_dump($hoge->hoge2);
$hoge->change2();
var_dump($hoge->hoge2);