使 PHP 对象表现得像一个数组?

Posted

技术标签:

【中文标题】使 PHP 对象表现得像一个数组?【英文标题】:Making a PHP object behave like an array? 【发布时间】:2010-09-09 01:39:32 【问题描述】:

我希望能够编写一个行为类似于数组并使用普通数组语法进行获取和设置的 php 类。

例如(其中 Foo 是我制作的 PHP 类):

$foo = new Foo();

$foo['fooKey'] = 'foo value';

echo $foo['fooKey'];

我知道 PHP 有 _get 和 _set 魔术方法,但它们不允许您使用数组表示法来访问项目。 Python 通过重载 __getitem__ 和 __setitem__ 来处理它。

有没有办法在 PHP 中做到这一点?如果它有所作为,我正在运行 PHP 5.2。

【问题讨论】:

【参考方案1】:

如果你扩展ArrayObject 或实现ArrayAccess,那么你可以做你想做的事。

ArrayObject ArrayAccess

【讨论】:

非常酷。似乎其中任何一个都不能与 array_key_exists 等数组函数一起使用。对吗? 正确,改用 offsetExist() 方法。 我会在实例化对象本身上这样做吗? if( $foo->offsetExists('fooKey') ) 我相信你可以使用 isset,但你不能使用 array_key_exists。 将 ArrayObject 转换为 Array 以将其与数组函数一起使用,例如数组值((数组)$some_array_object)。这是一个烦人的额外步骤,但它确实有效。【参考方案2】:

不,强制转换只会产生一个普通的 PHP 数组——失去 ArrayObject 派生类所具有的任何功能。看看这个:

class CaseInsensitiveArray extends ArrayObject 
    public function __construct($input = array(), $flags = 0, $iterator_class =     'ArrayIterator') 
        if (isset($input) && is_array($input)) 
            $tmpargs = func_get_args();
            $tmpargs[0] = array_change_key_case($tmpargs[0], CASE_LOWER);
            return call_user_func_array(array('parent', __FUNCTION__), $tmp    args);
        
        return call_user_func_array(array('parent', __FUNCTION__), func_get_args());
    

    public function offsetExists($index) 
        if (is_string($index)) return parent::offsetExists(strtolower($index));
        return parent::offsetExists($index);
    

    public function offsetGet($index) 
        if (is_string($index)) return parent::offsetGet(strtolower($index));
        return parent::offsetGet($index);
    

    public function offsetSet($index, $value) 
        if (is_string($index)) return parent::offsetSet(strtolower($index, $value));
        return parent::offsetSet($index, $value);
    

    public function offsetUnset($index) 
        if (is_string($index)) return parent::offsetUnset(strtolower($index));
        return parent::offsetUnset($index);
    


$blah = new CaseInsensitiveArray(array(
    'A'=>'hello',
    'bcD'=>'goodbye',
    'efg'=>'Aloha',
));

echo "is array: ".is_array($blah)."\n";

print_r($blah);
print_r(array_keys($blah));

echo $blah['a']."\n";
echo $blah['BCD']."\n";
echo $blah['eFg']."\n";
echo $blah['A']."\n";

正如预期的那样,array_keys() 调用失败。此外,is_array($blah) 返回 false。但是如果将构造函数行更改为:

$blah = (array)new CaseInsensitiveArray(array(

然后你只得到一个普通的 PHP 数组(is_array($blah) 返回 true,并且 array_keys($blah) 有效),但是 ArrayObject 派生的子类的所有功能都丢失了(在这种情况下,不区分大小写键不再起作用)。尝试以两种方式运行上述代码,你就会明白我的意思了。

PHP 应该提供一个本机数组,其中的键不区分大小写,或者使 ArrayObject 可转换为数组而不会丢失子类实现的任何功能,或者只是让所有数组函数接受 ArrayObject 实例。

【讨论】:

以上是关于使 PHP 对象表现得像一个数组?的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中,2D 数组的整体操作是不是比 1D 数组表现得像 2D 数组?

如何使 Recycler View 表现得像 PlayStore Recycler Views

使 UIScrollView 表现得像 UIPageControl

htmx:如何使每一行表现得像一个表格?

如何使 Material UI 图标表现得像锚标签?

如何使 ProcessPoolExecutor 中的任务表现得像守护进程?