2017-01-08 6 views
0

:이 사유 재산의 접근을 진정으로 제한 할 수 있습니까? 내 시도에서 세 가지 트릭을 사용하고

  • 반사 동적 클래스의 속성
  • __get() 또는 __set() 동적 클래스 속성을
  • debug_backtrace에 액세스 할 때 호출해야을 사용할 수 없습니다 (가) 비공개가 아닌 정적 속성 $bar와 클래스 Foo를 들어 private

에 비슷한 모방 활용 될 수있다, 나는외부의 범위를 허용하지 않으려을 입력하여 값을 수정하십시오. 그러므로 나는 이런 식으로 일을 해요 :

/** @property object $bar */ 
class Foo{ 
    public function __get($k){ 
     if($k === "bar") return $this->bar; 
    } 
    public function __set($k, $v){ 
     if($k === "bar"){ 
      $trace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS); 
      if($trace[0]["object"] !== $this or $trace[0]["file"] !== __FILE__) throw new RuntimeException("Illegal access"); 
      $this->bar = $v; 
     } 
    } 
} 

이해야한다 (테스트하지) 액세스 세 가지 종류에 상처를 입힐 수 : 호출하는 경우

  • 직접 액세스
    • debug_backtrace() 검사 컨텍스트는 $ this에서 온 것입니다. $ this 외부의 직접 액세스는 허용되지 않습니다.
  • ReflectionProperty
    • PHP 치명적인 오류 : catch되지 않은 ReflectionException : 부동산의 줄이 동적 속성 작동하지 않습니다
    • 반사를 존재하지 않습니다. 심지어
  • Closure::bind
    • 테스트하지 ReflectionClass::hasProperty() :-)을 통해 그것의 존재를 감지하지 않습니다,하지만 난 debug_backtrace()가 FILE 다르다 "파일"뭔가를 반환해야 생각하지만, 오히려 Closure를 정의한 파일. Foo의 올바른 사용법 만 있으므로 정확한 코드가로드되어있는 한 신경 쓰지 않아도됩니다.

Foo->bar 속성을 변경하려면로드 할 수있는 모든 파일을 기록 할 수있는 권한 및 클래스 메소드를 재정의하는 확장자 만, 임의의 PHP 코드가 없음을 어떤 방법이 있습니다 가정?

+0

클래스 외부의'$ bar' 속성에 대한 변경을 막으려 고합니다. 간단한'private $ bar'는 무엇이 잘못 되었나요? – Rei

+0

@RayRadin 이미 언급했듯이 반사를 통해 액세스 할 수 있습니다. 나는 반사가 동적 속성을 통해 그것을 만지는 것을 방지하려고 노력하고 있습니다. – SOFe

+0

알겠습니다. 그래서 객체 내부에 선언하지 않고'private $ bar'와 같은 동작을 원하십니까? – Rei

답변

1

약간의 조작을 한 후에, 나는 당신이 성취하고자하는 것이 불가능하고 또한 무의미하다고 결론을 내렸다. 이유를 설명하겠습니다. 을 보호공공, 및 개인 :

클래스의 속성은 3 가능한 가시성을 가지고있다. 이 공공 경우 , 당신은 간단한 과제로 값을 수정할 수 있습니다

$foo->bar = "new value"; 

우리가 __set() 이것을 가로 챌 수 있습니까?PHP Manual에서 :

__set() is run when writing data to inaccessible properties.

공공 속성은 항상 액세스 할 수 있습니다. 따라서 __set()이 호출되지 않으므로 사용자의 수표를 가로 채고 점검 할 기회가 없습니다. 속성이 보호 또는 개인경우

다음으로, 당신은 당신이 그 값을 수정 ReflectionProperty 또는 Closure::bind를 사용할 수 있다는 것을 의미 클래스, 에 선언해야합니다.

마지막으로 실제로 다른 값을 저장하여 __set()이 호출되는지 확인할 수 있습니다. 예를 들어, 같은 개체 또는 다른 개체의 다른 이름으로. 불행히도 값을 저장하는 위치에 관계없이 위의 설명이 다시 적용됩니다. 이것이 이유가 없습니다.

+0

좋은 재귀! 그래서 우리가 다른 이름을 생성하는 소금을 저장하고 싶다면 우선 그 소금을 개인용 어딘가에 저장해야합니다 : P 나는 지역 변수가 진정으로 사적이라는 것을 깨달았습니다. 역 추적 확장을 통해 액세스 할 수 있는지 살펴 보겠습니다. 나는 이것이 정말로 무의미하다는 것을 안다. – SOFe

+1

@PEMapModder 예, 가능할지 모르겠으므로 좋은 정신 운동이었습니다. 나는 그것을 좋아한다. – Rei