【问题标题】:Detect changes to Array in PHP在 PHP 中检测对数组的更改
【发布时间】:2013-12-09 06:04:21
【问题描述】:

我一直在使用带有受保护属性的 __set 魔术方法来监视更改,以便我的类知道它们是否有要保存的东西。有没有办法监控数组类型属性的变化?我知道通常您通过引用访问数组,并且像 array_push 这样的函数不会触发 __set 方法,它们会使用对数组的引用。

我想要的基本上是这样的:

class Skill{ public $Player, $Name, $Level;}
class Player {
    protected $Name, /*Other properties*/, $Skills /*Array*/
}

然后我跟踪 Player 中的所有属性,告诉我是否需要更新持久性。 (技能也会有这个功能,但这显示了基本示例)。另外,我想强制它们保持同步(这是一种双向关系)。

有什么方法可以让它表现得像一个数组(如果我不需要的话,不想通过创建一个类来同步它们)。

【问题讨论】:

    标签: php arrays change-tracking


    【解决方案1】:

    您可以扩展 ArrayObject 和代理附加:

    class Skills extends ArrayObject
    {
        public function append($value)
        {
            // track changes
            parent::append($value);
        }
    }
    

    【讨论】:

    • 这看起来正是我想要的。稍后我会测试它的适用性。不知道 ArrayObject。这太酷了。我必须改变更多,并且会调用对象只是更改跟踪数组并为构造函数提供一个字段名称以保持同步(包括从数组中删除)。简而言之,这让我可以创建一个简单的类来充当垫片,这 98% 是我想要的。 (我希望根本没有课程,在数组所属的课程中进行跟踪,但最好的解决方案并不总是适合您原始模式的那个)。
    • 很高兴这对您有所帮助,这与您当前的实现有点不同,但事实上,根据定义它ArrayObject implements IteratorAggregate , ArrayAccess , Serializable , Countable 意味着您可以像使用数组一样使用对象 (php.net/manual/en/class.arrayaccess.php)
    • 请注意,PHP 不会将 ArrayObject(或 ArrayAccess 等)视为数组。 array_* 方法将失败,+ 运算符将失败等等。
    【解决方案2】:

    您可以查看runkit_function_redifine() 之类的内容,但是为您想要的帮助方法真的太麻烦了吗?例如

    class Player
    {
        private $skills = array();
    
        protected function addSkill($skill)
        {
            // Do something.
            //
    
            $this->skills[] = $skill;
        }
    }
    

    甚至是数组的包装器以使其更清晰:

    class FancyArray
    {
        private $content = array();
    
        public function add($value)
        {
            // Do something.
            //
    
            $this->content[] = $value;
        }
    
        public function remove($value){ /* blah */ }
    
        public function getContent(){ return $this->content; }
    }
    
    class Player
    {
        protected $skills;
    
        public function __construct()
        {
            $this->skills = new FancyArray();
            $this->skills->add("Ninjitsu");
        }
    }
    

    【讨论】:

    • 这并不是说它太麻烦(烦人,但可行),而是我真的希望有更好的解决方案。我也不想为每个这样的项目编写特殊的代码(我试图使这个项目尽可能地可重用,因为我还有两个需要几乎相同的架构的作品)。这个解决方案确实必须为每个这样的数组(其中会有很多)单独开发。
    • @lassombra 我不确定为什么您认为后一个示例 (FancyArray) 在每次实施时都需要进行个性化。这是一个可以回收的类。
    • 错过了那部分。那(就像下面的答案)几乎就是我所追求的。正如我所说的那样,我希望玩家类可以监视(同时允许保留数组功能)对数组的更改,而无需编写单独的类。幸运的是,单独的类不需要进行很多更改。现在的挑战是我只能接受一个答案...
    • @lassombra 在我看来,另一个答案更接近你所追求的,考虑到你特别提到你不想建立一个中间类来管理状态变化;我只是想提出,它实际上并没有你想象的那么乏味。
    • 我很好奇的是我可以使用“花式数组”array_push($this->skills, $newskill) 并让它工作吗?如果是这样,那么你的实际上更精确地达到了我想要完成的目标。
    猜你喜欢
    • 2023-04-11
    • 1970-01-01
    • 2018-09-20
    • 2021-02-06
    • 1970-01-01
    • 2021-05-21
    • 2015-09-10
    • 1970-01-01
    • 2013-02-21
    相关资源
    最近更新 更多