Berry의 답변을 확장하기 위해 액세스 수준을 protected로 설정하면 __get 및 __set을 명시 적으로 선언 된 속성 (적어도 클래스 외부에서 액세스 할 때)과 함께 사용할 수 있고 속도가 상당히 느려진다는 점에서 다른 질문에서 의견을 인용하겠습니다. 이 주제에 대해 어쨌든 그것을 사용하는 사례를 만드십시오.
나는 __get이 사용자 정의 get 함수 (동일한 일을 수행)보다 느리다는 데 동의합니다. 이것은 __get ()의 시간 인 0.0124455이고이 0.0024445는 10000 루프 후 사용자 정의 get ()을위한 것입니다. – Melsi 11 월 23 일 '12 년 11 월 23 일 22:32 모범 사례 : PHP 매직 메서드 __set 및 __get
Melsi의 테스트에 따르면 상당히 느린 것은 약 5 배 느립니다. 이는 확실히 상당히 느리지 만 테스트에서이 메서드를 사용하여 약 1/100 초 내에 루프 반복 시간을 계산하여 10,000 번 속성에 액세스 할 수 있음을 보여줍니다. 정의 된 실제 get 및 set 메서드에 비해 상당히 느리며 이는 과소 표현이지만, 대대적 인 계획에서는 5 배 더 느리더라도 실제로는 느리지 않습니다.
작업의 컴퓨팅 시간은 여전히 미미하며 실제 애플리케이션의 99 %에서 고려할 가치가 없습니다. 실제로 피해야하는 유일한 경우는 단일 요청에서 실제로 10,000 번 이상 속성에 액세스 할 때입니다. 트래픽이 많은 사이트는 애플리케이션을 계속 실행하기 위해 몇 대의 서버를 추가로 투입 할 여유가 없다면 정말 잘못된 일을하고 있습니다. 액세스 속도가 문제가되는 트래픽이 많은 사이트의 바닥 글에 한 줄 텍스트 광고는 해당 텍스트 줄이있는 1,000 대의 서버 팜에 비용을 지불 할 수 있습니다. 최종 사용자는 애플리케이션의 속성 액세스에 백만 분의 1 초가 걸리기 때문에 페이지를로드하는 데 너무 오래 걸리는 것이 무엇인지 궁금해하지 않을 것입니다.
나는 이것이 .NET의 배경에서 온 개발자라고 말하지만, 소비자에게 보이지 않는 get 및 set 메서드는 .NET의 발명이 아닙니다. 그것들은 단순히 그것들이없는 속성이 아니며, 이러한 마법의 방법은 심지어 속성의 버전을 "속성"이라고 부르는 것에 대한 PHP의 개발자의 은혜입니다. 또한 PHP 용 Visual Studio 확장은 보호 된 속성을 사용하여 인텔리 젠스를 지원합니다. 이러한 트릭을 염두에두고 있습니다. 이런 식으로 매직 __get 및 __set 메서드를 사용하는 개발자가 충분하면 PHP 개발자가 개발자 커뮤니티에 맞게 실행 시간을 조정할 수 있다고 생각합니다.
편집 : 이론적으로 보호 된 재산은 대부분의 상황에서 작동하는 것처럼 보였습니다. 실제로 클래스 정의 및 확장 클래스 내에서 속성에 액세스 할 때 getter 및 setter를 사용하려는 경우가 많습니다. 더 나은 솔루션은 다른 클래스를 확장 할 때의 기본 클래스 및 인터페이스이므로 기본 클래스에서 구현 클래스로 코드 몇 줄만 복사하면됩니다. 내 프로젝트의 기본 클래스로 조금 더 작업하고 있으므로 지금 제공 할 인터페이스가 없지만 여기에는 속성을 제거하고 이동하기 위해 리플렉션을 사용하여 설정하고 마법 속성을 가져 오는 테스트되지 않은 제거 된 클래스 정의가 있습니다. 보호 된 어레이 :
class Component {
protected $properties = array();
public function __get($name) {
$caller = array_shift(debug_backtrace());
$max_access = ReflectionProperty::IS_PUBLIC;
if (is_subclass_of($caller['class'], get_class($this)))
$max_access = ReflectionProperty::IS_PROTECTED;
if ($caller['class'] == get_class($this))
$max_access = ReflectionProperty::IS_PRIVATE;
if (!empty($this->properties[$name])
&& $this->properties[$name]->class == get_class()
&& $this->properties[$name]->access <= $max_access)
switch ($name) {
default:
return $this->properties[$name]->value;
}
}
public function __set($name, $value) {
$caller = array_shift(debug_backtrace());
$max_access = ReflectionProperty::IS_PUBLIC;
if (is_subclass_of($caller['class'], get_class($this)))
$max_access = ReflectionProperty::IS_PROTECTED;
if ($caller['class'] == get_class($this))
$max_access = ReflectionProperty::IS_PRIVATE;
if (!empty($this->properties[$name])
&& $this->properties[$name]->class == get_class()
&& $this->properties[$name]->access <= $max_access)
switch ($name) {
default:
$this->properties[$name]->value = $value;
}
}
function __construct() {
$reflected_class = new ReflectionClass($this);
$properties = array();
foreach ($reflected_class->getProperties() as $property) {
if ($property->isStatic()) { continue; }
$properties[$property->name] = (object)array(
'name' => $property->name, 'value' => $property->value
, 'access' => $property->getModifier(), 'class' => get_class($this));
unset($this->{$property->name}); }
$this->properties = $properties;
}
}
코드에 버그가 있으면 사과드립니다.