2009-12-22 4 views
4

개체에서 새 속성을 만들 수 있습니다. 그러나 누군가가 설명 할 수 있습니까? setAttrib이 두 가지 다른 방식으로 작동하는 이유는 무엇입니까? 왜 그게 ... 기다려 ... 스택 오버플로 !!PHP : 매번 다른 함수 동작 __set

class Test 
{ 
    public function setAttrib($key, $value) { 
    echo "setAttrib\n"; 

    // first time: calls $this->__set($key, $value) 
    // second time: just sets a public property (but, when exactly was it created?) 
    $this->$key = $value; 
    } 

    public function __set($key, $value) { 
    echo "__set\n"; 
    $this->setAttrib($key, $value); 
    } 
} 

$test = new Test(); 
$test->setAttrib('hey', 'It works'); 
var_dump($test); 

은 ...

setAttrib 
__set 
setAttrib 
object(Test)#1 (1) { 
    ["hey"]=> 
    string(8) "It works" 
} 

편집을 생산 : 내가 대안을 찾는 게 아니에요. 나는 이것이 작동하는 이유를 찾고 있습니다.

+0

아무 것도 변경하지 않지만 __set 메서드는 public이어야합니다 (http://www.php.net/manual/en/language.oop5.overloading.php 참조). "모든 오버로드 메서드 public으로 정의해야합니다. "- 코드를 실행할 때 얻게되는 경고문) –

+0

네가 바로 거기에 있으며 나는 그것을 공개로 바 꾸었습니다. 같은 행동. –

+1

적어도, 그것은 더 이상의 ^^ (내가 다른 것을 바꿀 것이라고는 생각하지 않았기 때문에 나는 단지 코멘트를 올린 것입니다. 그러나 한 가지 경고는 항상 좋은 것입니다) –

답변

8

당신은 통지를 갖고있는 것 같아요 유일한되지 않은 비 재귀 행동 : this comment on the manual's page 상태 :

2 - PHP는 재귀에 대한 최소한 에서 자체 (내에서 하나 개 마법 메소드를 호출하지 않습니다 동일 $name).

재귀 감지 기능이 특히 위험한 증명할 수 __set를 사용하는 경우 :

그리고는 잠시 후 같은 페이지에, 상태 this one,있다. PHP는 일반적으로 __set를 부를 것이다 단순히 모두에 정의 된 __set 방법이없는 것처럼이 역할을 할 명령문을 실행하지 경고 또는 을 발사하는 대신, 재귀에 을 이끌 것 문을 통해 제공합니다.
이 인스턴스의 기본 동작은 동적으로하여 그 속성에 대한 __set 또는 __get에 모든 추가 통화의 원하는 기능을 깨는 개체에 지정된 속성 를 추가 이다.


그리고, PHP의 bugtracker에,라고하는 #47215 : magic method __set() is bypassed on recursive call가 :

매직이 방법 __set()은 재귀 호출에 무시됩니다.

가 시간을 내 주셔서 감사합니다
PHP 자동으로 인스턴스의 속성 반복적으로 __set() 또는 를 호출하는 대신 recursivity에게 오류

그리고는 다음과 같이 닫힌를 던지는 대신 를 생성 을 작성하십시오. 그러나 이것은 버그가 아닙니다. 나는 그것이 버그 하지만 예상하지 않을 수 있습니다 생각 결국

:

버그 보고서는 자체가, (인용, 강조 광산)이 문장 으로 끝나는, this blog-post를 가리키는 동작, 그렇지 않으면 우리 __set() 방법 내에서 개체를 정의 할 수 없습니다.

+0

필자에게 PHP는 __set()을 cursively 호출하고 있으며, 내 견과를 몰아 가고 있으며, 동적으로 속성을 정의 할 수없고 같은 클래스에서 마술 __set을 사용할 수 없습니다. 나는 PHP 5.3.2를 사용하고있다. 그들은이 행동을 바꿨습니까, 아니면 제가 잘못 생각 했습니까? –

2

__set은 액세스 할 수없는 속성에 쓸 때만 사용됩니다. 즉, 액세스 할 수없는 (개인 또는 보호 된) 사람 또는 전혀 설정되지 않은 사람입니다. 따라서 __set은 한 번만 호출됩니다.

여기 무슨 일이야 :

  • setAttrib : 시도는
  • 클래스 작성 : 액세스 속성을
  • __set : 다시 전화 setAttrib이다, 할 말 무엇이든지 __set 마십시오.
  • setAttrib : 쓰기 시도
  • 클래스 : 액세스 할 수없는 속성이지만 __set은 재귀를 사용할 수 없으며 이미 __set이 존재하므로 __set이없는 것처럼 처리하십시오.

__set을 재귀 할 수 없다는 증거로 http://php.net/__set에 대한 사용자 의견보기.

+0

나는 궁금합니다. 정확히 언제 '헤이'회원이 생겼습니까? 여기에 눈을 맞추는 것 이상의 것이 있습니다. –

+0

이것은 setAttrib의 마지막 실행시 기록됩니다. –

+0

속성을 설정하는 첫 번째 호출에서 발생합니다. '__set'은 당신이'$ a = new MyClass(); $ a-> hey = 'my text';'MyClass :: $ hey'에 접근 할 수없는 클래스 내에서. – prodigitalson

0

__set__get은 회원이 보호되어있는 경우에만 속성 호출을 수신합니다. 즉 객체 내에서 $this->$key은 속성 $key을 설정합니다. 범위 밖에서 호출되면 __set 논리가 호출됩니다. 호출 중 하나가 객체 외부의 객체에서 발생합니다.