2010-11-05 2 views
3

Would делать это можно считать хорошей практикой ...PHP Магические методы __set и __get

У меня есть класс A со следующими определениями:

class A{ 
     private $_varOne; 
     private $_varTwo; 
     private $_varThree; 
     public $varOne; 


     public function __get($name){ 

    $fn_name = 'get' . $name; 

     if (method_exists($this, $fn_name)){ 
      return $this->$fn_name(); 
    }else if(property_exists('DB', $name)){ 
      return $this->$name; 
    }else{ 
    return null; 
    } 
     } 

    public function __set($name, $value){ 

    $fn_name = 'set' . $name; 

    if(method_exists($this, $fn_name)){ 
    $this->$fn_name($value); 
    }else if(property_exists($this->__get("Classname"), $name)){ 
    $this->$name = $value; 
    }else{ 
    return null; 
    } 

    } 

     public function get_varOne(){ 
      return $this->_varOne . "+"; 
     } 


} 

$A = new A(); 
$A->_varOne;  //For some reason I need _varOne to be returned appended with a + 

$A->_varTwo;  //I just need the value of _varTwo 

Для того, чтобы не создавать 4 набора и 4 методов получения , Я использовал магические методы, чтобы либо вызвать уважаемого геттера для свойства, которое мне нужно, либо просто вернуть значение свойства без каких-либо изменений. Может ли это считаться хорошей практикой?

ответ

7

Не знаю о лучших практиках, но __get чрезвычайно полезен, когда вам нужно, чтобы свойство было ленивым, например, при его получении происходит сложная кальцификация или запрос db. Кроме того, php обеспечивает элегантный способ кэширования ответа путем простого создания поля объекта с тем же именем, что предотвращает повторное вызов getter.

class LazyLoader 
{ 
    public $pub = 123; 

    function __get($p) { 
     $fn = "get_$p"; 
     return method_exists($this, $fn) ? 
      $this->$fn() : 
      $this->$p; // simulate an error 
    } 

    // this will be called every time 
    function get_rand() { 
     return rand(); 
    } 

    // this will be called once 
    function get_cached() { 
     return $this->cached = rand(); 
    } 
} 

$a = new LazyLoader; 
var_dump($a->pub);  // getter not called 
var_dump($a->rand);  // getter called 
var_dump($a->rand);  // once again 
var_dump($a->cached); // getter called 
var_dump($a->cached); // getter NOT called, response cached 
var_dump($a->notreally); // error! 
+2

+0 - в то время как я согласен, что это замечательно изящно, это возможно только в том случае, если вы не верите в использование ключевых слов видимости и декларации переднего класса (я знаю, что вы не делаете). Для всех остальных это пример, почему вы не следует использовать магические методы для этой цели, потому что '$ a-> rand' будет намного медленнее, чем просто вызвать' get_rand' напрямую – Gordon

2

Вы пришли с Java, не так ли?

В любом случае, если вы просто получаете и устанавливаете эти свойства без разбора, просто сделайте их общедоступными. Используйте __get, __set и частные свойства, если вам нужно сделать что-то еще с данными, кроме просто присваивания и чтения из переменных.

Кроме того, вы, вероятно, увидите, что часто говорят, что магические методы затрудняют производительность и т. Д., Но это должно быть действительно опасно в сценариях с высоким уровнем использования - чаще всего узким местом будет дисковый ввод-вывод, база данных или в некоторых случаях операции с интенсивным использованием памяти/ЦП

3

Это можно считать хорошей практикой?

Зависит от того, какую проблему вы пытаетесь решить, но, в общем, нет. Я пришел из школы мысли, что магические методы должны использоваться только для решения существующих проблем, которые не могут быть решены каким-либо другим практическим способом, а не использовать их в качестве основы для проектирования.

Так много всего, что вы делаете, можно обрабатывать с помощью реальных геттеров/сеттеров. PHP не имеет истинных свойств, поэтому принудительное их на ваших классах определенно идет против зерна.

+1

Итак, для чего следует использовать гибкое и многоразовое решение, которое уменьшает код, когда вы могли бы _just_ рисовать все, используя избыточную логику в нескольких функциях «наполнителя»? Не так ли? Чье время более ценно, процессор или программист? Я получаю менталитет «горы глупых деталей» из лагеря Java, но PHP немного более прагматичен и «по сути».« – HonoredMule

1

Нет, это не потому, что эти магические методы являются перехватчиками, которые могут обрабатывать любые вызовы недоступных свойств до того, как PHP выдает ошибку об этом. Они не заменят правильных геттеров и сеттеров.

They also behave differently as stated in the Manual:

Возвращаемое значение __set() игнорируется из-за способа РНР обрабатывает оператор присваивания. Аналогично, __get() никогда не вызывается при объединении назначений вместе следующим образом: $ a = $ obj-> b = 8;

Они также являются slower to execute with a significant performance impact. API также будет менее прозрачным, потому что все, что волшебным образом делает что-то, озадачивает.

Смежные вопросы