Jose Vega
Jose Vega

Reputation: 10258

PHP Magic Methods __set and __get

Would doing this be consider good practice...

I have class A with the following definitions:

 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?

Upvotes: 3

Views: 1772

Answers (4)

user187291
user187291

Reputation: 53940

Don't know about best practices, but __get comes extremely useful when you need a property to be lazy loaded, e.g. when getting it involves a complex calcification or a db query. 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.

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!

Upvotes: 7

Gordon
Gordon

Reputation: 316969

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. 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. Similarly, __get() is never called when chaining assignments together like this: $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.

Upvotes: 1

webbiedave
webbiedave

Reputation: 48897

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. PHP does not have true properties so forcing them upon your classes is definitely going against the grain.

Upvotes: 3

pilsetnieks
pilsetnieks

Reputation: 10420

You are coming from Java, aren't you?

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.

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

Upvotes: 2

Related Questions