8

I've found the piece of code below in several places around the web and even here on Stack Overflow, but I just can't wrap my head around it. I know what it does, but I don't know how it does it even with the examples. Basically it's storing values, but I don't know how I add values to the registry. Can someone please try to explain how this code works, both how I set and retrieve values from it?

class Registry {

    private $vars = array();

    public function __set($key, $val) {
        $this->vars[$key] = $val;
    }

    public function __get($key) {
        return $this->vars[$key];
    }
}
beng
  • 39
  • 6
Ian Hoar
  • 1,174
  • 1
  • 19
  • 40
  • You should prevent the set function from overwriting with something like the following (also uses array_key_exists, should use for both set and get in this case) which is probably just as important as not using non-existent keys because the whole purpose of the registry is to store information, which is kind of defeated by the possibility of overwriting: `public function set($key, $val) { if (!array_key_exists($key, $this->_nfo)) { $this->_nfo[$key] = $val; } }` – Nate Jul 22 '13 at 23:32

2 Answers2

8

It's using PHP's hacked on property overloading to add entries to and retrieve entries from the private $vars array.

To add a property, you would use...

$registry = new Registry;
$registry->foo = "foo";

Internally, this would add a foo key to the $vars array with string value "foo" via the magic __set method.

To retrieve a value...

$foo = $registry->foo;

Internally, this would retrieve the foo entry from the $vars array via the magic __get method.

The __get method should really be checking for non-existent entries and handle such things. The code as-is will trigger an E_NOTICE error for an undefined index.

A better version might be

public function __get($key)
{
    if (array_key_exists($key, $this->vars)) {
        return $this->vars[$key];
    }

    // key does not exist, either return a default
    return null;

    // or throw an exception
    throw new OutOfBoundsException($key);
}
Phil
  • 157,677
  • 23
  • 242
  • 245
  • Thanks, I thought I was going crazy. This helped me go back and check what was going on. I was trying to set a form action, but it was always coming up blank. Turns out I was on the index page, so there was no value. DOH!. I tried the form on another page and it worked fine. Thanks for your help. When you say hacked on, does that mean it shouldn't be used this way? – Ian Hoar Nov 16 '11 at 06:20
  • @IanHoar Well, it definitely shouldn't be called *overloading* – Phil Nov 16 '11 at 06:23
  • @Phil I can see how you add the key, but how do you add a key-value pair? – Wolfpack'08 Nov 07 '12 at 05:07
  • 1
    @Wolfpack Not sure what you mean. When you set `$registry->key = 'value'`, internally it stores a key / value pair of `key` and `value` respectively but to the outside world, they appear as class properties – Phil Nov 07 '12 at 05:13
  • `$foo = $registry->foo;` ; `$foo = $registry->foo = 'bar';`? I don't full understand the purpose of this code, honestly. I'm just reading articles. – Wolfpack'08 Nov 07 '12 at 05:14
  • @Wolfpack still not sure what your question is. Your first snippet uses the `__get()` method to retrieve property `foo` and assign the value to local var `$foo`. Your second assigns `'bar'` to both the property `foo` and local variable `$foo`. It's no different to `$a = $b = 'some value'` – Phil Nov 07 '12 at 05:16
  • @Phil I was just following the template: `$registry->key = 'value'` – Wolfpack'08 Nov 07 '12 at 06:20
8

You might want to check out PHP.NET - Overloading

Basically, you would do...

$Registry = new Registry();

$Registry->a = 'a'; //Woo I'm using __set
echo $Registry->a; //Wooo! I'm using __get

So here, I'm using __set($a, 'This value is not visible to the scope or nonexistent') Also, I'm using __get($a);

Hope this helped!