2010-08-13 8 views
2

__get() 및 __set()을 사용하여 마스터 배열의 배열 요소를 저장하고 검색하는 클래스를 작성했습니다. 기본적으로 개인 속성을 다시 생성하기 위해 일부 요소를 잊을 수 없도록 만드는 체크가있었습니다.__get() 및 __set()을 사용하여 공개/비공개 속성을 에뮬레이트 하시겠습니까?

__get이 클래스 속성에 대한 모든 호출을 가로 채는 것으로 보입니다. 외부 세계에 변수를 개인적으로 갖기를 원했기 때문에 (get을 통해 사용할 수 없음), 클래스 내에서 직접 마스터 배열을 참조하여 변수에 액세스하려고했기 때문에 이것은 나를 괴롭힌다. 물론, 마스터 배열은 내가 __get() 그리고 __set()를 사용하는 PHP 클래스에서 공공 및 민간 특성을 에뮬레이션 할 수있는 방법이 getTable이 속성 :(

의 화이트리스트에 있는가 아닌가?

예 :

<? 

abstract class abstraction { 

    private $arrSettables; 
    private $arrGettables; 
    private $arrPropertyValues; 
    private $arrProperties; 

    private $blnExists = FALSE; 

    public function __construct($arrPropertyValues, $arrSettables, $arrGettables) { 

     $this->arrProperties = array_keys($arrPropertyValues); 
     $this->arrPropertyValues = $arrPropertyValues; 
     $this->arrSettables = $arrSettables; 
     $this->arrGettables = $arrGettables; 
    } 

    public function __get($var) { 
     echo "__get()ing:\n"; 
     if (! in_array($var, $this->arrGettables)) { 
      throw new Exception("$var is not accessible."); 
     } 

     return $this->arrPropertyValues[$var]; 
    } 

    public function __set($val, $var) { 
     echo "__set()ing:\n"; 
     if (! in_array($this->arrSettables, $var)) { 
      throw new Exception("$var is not settable."); 
     } 

     return $this->arrPropertyValues[$var]; 
    } 

} // end class declaration 

class concrete extends abstraction { 

    public function __construct($arrPropertyValues, $arrSettables, $arrGettables) { 
     parent::__construct($arrPropertyValues, $arrSettables, $arrGettables); 
    } 

    public function runTest() { 

     echo "Accessing array directly:\n"; 
     $this->arrPropertyValues['color'] = "red"; 
     echo "Color is {$this->arrPropertyValues['color']}.\n"; 

     echo "Referencing property:\n"; 
     echo "Color is {$this->color}.\n"; 
     $this->color = "blue"; 
     echo "Color is {$this->color}.\n"; 

     $rand = "a" . mt_rand(0,10000000); 
     $this->$rand = "Here is a random value"; 
     echo "'$rand' is {$this->$rand}.\n"; 

    } 
} 

try { 
    $objBlock = & new concrete(array("color"=>"green"), array("color"), array("color")); 
    $objBlock->runTest(); 
} catch (exception $e) { 
    echo "Caught Exeption $e./n/n"; 
} 

// no terminating delimiter 

$ php test.php 
Accessing array directly: 
__get()ing: 
Caught Exeption exception 'Exception' with message 'arrPropertyValues is not accessible.' in /var/www/test.php:23 
Stack trace: 
#0 /var/www/test.php(50): abstraction->__get('arrPropertyValu...') 
#1 /var/www//test.php(68): concrete->runTest() 
#2 {main}. 

답변

1

내가 __get() 그리고 __set()를 사용하는 PHP 클래스에서 공공 및 민간 특성을 에뮬레이션 할 수있는 방법이 있나요

하지 direc? tly (할인한다면 debug_backtrace).

그러나 현재 __get의 모든 작업을 수행하는 개인 방법 getPriv을 사용할 수 있습니다. 그런 다음 __get은이 개인용 메소드를 랩핑하고 액세스 가능성을 점검합니다. 클래스 내부

function __get($name) { 
    if (in_array($name), $this->privateProperties) 
     throw new Exception("The property ". __CLASS__ . "::$name is private".); 
    return $this->getPriv($name); 
} 

, 당신은 이렇게 __get을 우회, getPriv을 부를 것이다.

+0

그러나 여전히 문제가있다 : – user151841

+0

나는 깜짝 놀랄거야! 그것은 작동합니다! 하지만 왜? 그것은'__get()'이 원래 클래스에서 인터셉트하지 않기 때문입니까? – user151841

+1

@user 원래 클래스에서 인터셉트를합니다. 따라서 클래스 내부에서'getPriv'를 호출해야합니다. 내가 당신을 이해하는지 모르겠다. 그러나 속성이 명시 적으로 선언되어 있다면'__get'은 메소드 호출이나 속성 접근을 방해하지 않는다. – Artefacto

1

abstraction::getPriv()을 보호해야한다는 것을 제외하고는 abstraction::$arrPropertyValues을 보호하거나 Artefacto가 작성한 것을 수행합니다 (추가 검사가 필요한 경우). - 내가 배열,`getPriv()에 모든 것을 저장하고있어 이후`이

function __get($name) { 

    $reflect = new ReflectionObject($this); 
    $publics = $reflect->getProperties(ReflectionProperty::IS_PUBLIC); 

    if (in_array($name, $publics)) { 
     return $this->{$name}; 
    } 
} 
+0

트릭을 보호했습니다! – user151841

1

오히려 수동/개인 보호 특성을 입대하는 것은, 당신이 PHPs 성가신 반사 방법을 사용할 수있는 것보다

`$ arrPropertyValues` 클래스의 값을 참조하는 것입니다. 이것은`__get()`에 의해 인터셉트됩니다 ... 무한 루프입니까?
+0

Yummmm ... 귀찮은! :) – user151841

+1

정확하게 cucumbersome – mario

+0

음 ... Cummerbunds .... – user151841

관련 문제