tags:

views:

223

answers:

3

PHP 5 introduces the magic method __get() and __set(). From my understanding it is a shortcut for having to write each member's getter and setter;

 <?php
class Person {
    private $firstname;
    private $lastname;

    function __set($var, $name) {
        $this->$var = $name;
    }

    function __get($var) {
        return $this->$var;
    }
}

$person = new Person();
$person->firstname = "Tom";
$person->lastname = "Brady";


echo $person->firstname . " " . $person->lastname;

// print: Tom Brady
?>

My question is, this is just like making the member variables public.

class Person {
    public $firstname;
    public $lastname;
}

Isn't this against OOP principles? And what's the point?

A: 

First of all, your example shouldn't work because you're accessing $this->var.

Second: Yes, adding magic setters and getters is like adding setters and getters. Just magic.

There are uses for __set and __get: if you were building a library such as an ORM, it may come in handy. Also, it can be used as a poor-man's properties: if you had made a field public originally, you can now add behavior in __set and __get, as if it was always there (validation, for example).

Tordek
thx.. I changed the code to $this->$var. This is potential hard to debug code.
Yada
+3  A: 

In your example, it would be the same thing as making them public. However, your __set & __get functions don't have to process all variables. (maybe using a switch statement to decide which you want to process.) Also, you can perform data validation on the parameters to the __set or compute a return value for a __get that doesn't exist at all.

Just noticed that you are using $this->var instead of $this->$var in your code (which is what I think you intended for your code to work correctly)

Tom
+2  A: 

Something to be understood is that "OOP principles" aren't sent in stone. They are more like rules of thumb.

So for example in python all the member variables are public. There are no real private variables.

In Smalltalk all variables are private, there are no public variables if you want to provide access to a variable you need a getter. As a matter of fact here is where the getters and setters practice originated.

So the magic getters and setters in php can be useful on many circumstances. For example:

  • ORMappers
  • When you are building an object to send to an external API
  • When you want to identify someone accessed a variable.
  • etc.

Now if you want to keep private variables and still use magic getters and setters again for the specific case of your application you could modify your code to use the '_' underscore convention for private variables.

<?php
class Person {
    private $_firstname;
    private $_lastname;

    function __set($name, $value) {
        if (!strpos('_', $name) === 0) {
            $this->$name = $value;
        } else {
            throw new Exception ("trying to assign a private variable");
        }
    }

    function __get($name) {
        if (!strpos('_', $name) === 0) {
            retrun $this->$name;
        } else {
            throw new Exception ("trying to read a private variable");
        }
    }
}

?>
elviejo