Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP approach to python's magic __getattr__()

I was wondering if there was some way in PHP to duplicate some of the magic of Python attribute/key access.

I use a Mongo ORM class written by Steve Lacey called Minimongo in which he utilizes the __getattr__ and __getitem__ to reroute key and attribute flavored access and preserve the 'document-oriented' nature of Mongo. val = doc.foo and val = doc['foo'] become equivalent.

I was wondering if there is a similar interface in PHP that would allow the changing of how object access is handled for a class that inherits from it. I looked through the STL and couldn't find one that filled suit. It would be greatly useful for setting up defaults. Thanks.

like image 917
DeaconDesperado Avatar asked Dec 22 '22 04:12

DeaconDesperado


2 Answers

Have a look at __get() and __set() and ArrayAccess.

With the former you can make non-public members accessbile, as in $obj->foo, with the latter you can access them like $obj['foo'].

You can hardwire them however you like, internally.

Personally I would suggest you keep these magically-accessible properties into one single array member of the class, so you don't end up with spaghetti code.

POC:

 1  <?php
 2  class Magic implements ArrayAccess {
 3  
 4      protected $items = array();
 5  
 6      public function offsetExists($key) {
 7          return isset($this->items[$key]);
 8      }
 9      public function offsetGet($key) {
10          return $this->items[$key];
11      }
12      public function offsetSet($key, $value) {
13          $this->items[$key] = $value;
14      }
15      public function offsetUnset($key) {
16          unset($this->items[$key]);
17      }
18  
19      //do not modify below, this makes sure we have a consistent
20      //implementation only by using ArrayAccess-specific methods
21      public function __get($key) {
22          return $this->offsetGet($key);
23      }
24      public function __set($key, $value) {
25          $this->offsetSet($key, $value);
26      }
27      public function __isset($key) {
28          return $this->offsetExists($key);
29      }
30      public function __unset($key) {
31          $this->offsetUnset($key);
32      }
33  }
34  
35  //demonstrate the rountrip of magic
36  $foo = new Magic;
37  $foo['bar'] = 42;
38  echo $foo->bar, PHP_EOL;//output 42
39  $foo->bar++;
40  echo $foo['bar'];//output 43
41  

Consistency Milord, exactly as you asked.

like image 50
Flavius Avatar answered Dec 24 '22 01:12

Flavius


You should have a look at the Magic Methods of PHP: http://php.net/manual/en/language.oop5.magic.php

__get(), __set() and __call() could do what you want.

like image 25
TimWolla Avatar answered Dec 24 '22 01:12

TimWolla