简体   繁体   English

PHP Magic Methods __set和__get

[英]PHP Magic Methods __set and __get

Would doing this be consider good practice... 这样做会被认为是好的做法......

I have class A with the following definitions: 我有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

In order to not create 4 set and 4 get methods, I have used the magic methods to either call the respected getter for the property I need or just return the value of the property without any change.Could this be consider good practice? 为了不创建4个set和4个get方法,我使用了魔术方法来为我需要的属性调用受尊重的getter,或者只是返回属性的值而不做任何改变。这可以考虑这个好习惯吗?

Don't know about best practices, but __get comes extremely useful when you need a property to be lazy loaded, eg when getting it involves a complex calcification or a db query. 不了解最佳实践,但是当需要延迟加载属性时__get非常有用,例如,当获取它涉及复杂的钙化或数据库查询时。 Moreover, php provides an elegant way to cache the response by simply creating an object field with the same name, which prevents the getter to be called again. 此外,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!

Could this be consider good practice? 这可以算是好的做法吗?

Depends on what problem you're trying to solve but, in general, no. 取决于你想要解决的问题,但总的来说,没有。 I come from the school of thought that magic methods should only be used to solve existing problems that cannot be solved any other practical way, as opposed to using them as the basis for design. 我来自思想学派,魔术方法应该只用于解决任何其他实际方法无法解决的现有问题,而不是用它们作为设计的基础。

So much of what you're doing can be handled with real getters/setters. 你所做的很多事情都可以通过真正的getter / setter来处理。 PHP does not have true properties so forcing them upon your classes is definitely going against the grain. PHP没有真正的属性,所以强迫它们上课是绝对不利的。

You are coming from Java, aren't you? 你来自Java,不是吗?

Anyway, if you're just getting and setting those properties indiscriminately, just make them public. 无论如何,如果你只是不加选择地设置这些属性,只需将它们公之于众。 Use __get, __set and private properties if you need to do something else with the data apart from just assigning to and reading from variables. 如果除了分配和读取变量之外,还需要对数据执行其他操作,请使用__get,__ set和私有属性。

Also, you'll probably see that it is often said that magic methods hamper performance, etc. but that should only really be a concern in high-usage scenarios - most often the bottleneck will be disk I/O, database or in some cases memory/CPU-intensive operations 此外,您可能会看到通常会说魔术方法会妨碍性能等等,但这应该只是在高使用率情况下才会引起关注 - 通常瓶颈是磁盘I / O,数据库或某些情况下内存/ CPU密集型操作

No, it's not because these magic methods are interceptors that can handle any calls to inaccessible properties before PHP throws an error about it. 不,这不是因为这些魔术方法是拦截器,可以在PHP抛出错误之前处理对不可访问属性的任何调用。 They are not a substitute for proper getter and setters. 它们不能替代正确的吸气剂和制定者。

They also behave differently as stated in the Manual: 它们的行为也与手册中所述的不同:

The return value of __set() is ignored because of the way PHP processes the assignment operator. 由于PHP处理赋值运算符的方式,忽略__set()的返回值。 Similarly, __get() is never called when chaining assignments together like this: $a = $obj->b = 8; 类似地,在将赋值链接在一起时,永远不会调用__get():$ a = $ obj-> b = 8;

They are also slower to execute with a significant performance impact . 它们的执行速度较慢,会对性能产生重大影响 You API will also be less transparent because everything that magically does something is puzzling. 你的API也会变得不那么透明,因为所有神奇地做某事的东西都令人费解。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM