PHP 中如何实现 Python 的魔法 __getattr__()?

4 投票
2 回答
687 浏览
提问于 2025-04-17 09:33

我在想,PHP有没有办法能像Python那样方便地访问属性或键。

我使用了一个叫做Steve Lacey写的Mongo ORM类,名为Minimongo。在这个类里,他利用了__getattr____getitem__这两个功能,让我们可以用不同的方式来访问键和属性,同时保持Mongo的“文档导向”特性。比如说,val = doc.fooval = doc['foo']是等价的。

我想知道在PHP中是否有类似的接口,可以改变一个类的对象访问方式,特别是当这个类被其他类继承时。我查了一下标准库,但没找到合适的。这个功能如果能实现,会对设置默认值非常有帮助。谢谢。

2 个回答

2

你可以看看PHP的魔术方法:http://php.net/manual/en/language.oop5.magic.php

__get()__set()__call()可以帮你实现你想要的功能。

9

看看__get() 和 __set()以及ArrayAccess这两个内容。

使用前者,你可以让一些不公开的成员变得可以访问,比如像这样 $obj->foo,而使用后者,你可以像这样访问它们 $obj['foo']

你可以根据自己的需要在内部自由设置这些访问方式。

我个人建议把这些可以“魔法”访问的属性放到类的一个数组成员里,这样可以避免代码变得混乱。

示例代码:

 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  

保持一致性,正如你所要求的那样。

撰写回答