跟踪 PHP 对象属性更改

发布于 2024-08-01 14:36:01 字数 1870 浏览 1 评论 0原文

我正在尝试跟踪对 PHP 变量所做的所有更改。 该变量可以是对象或数组。

例如,它看起来像这样:

$object = array('a', 'b');

然后使用对象缓存将该对象持久保存到存储中。 当php脚本再次运行时。

因此,当脚本第二次运行时,或者另一个脚本运行并修改该对象时,我希望跟踪这些修改,无论是在完成时还是在脚本执行后一次性跟踪。

例如:

$object[] = 'c';

我想知道“c”已添加到对象中。

现在实际代码看起来像这样:

$storage = new Storage();
$storage->object = array('a', 'b');

第二次加载:

$storage = new Storage();

var_dump($storage->object); // array('a', 'b')

$storage->object[] = 'c';

我想知道的是 'c' 被推入 $storage->object 所以在类“Storage”中我可以将该值设置为持久存储。

我尝试了一些方法,虽然有效,但也有缺点。

1) 将所有对象包装在“Storable”类中,该类跟踪对象的更改

“Storable”类只是将实际数据对象保存为属性,然后提供 __get() 和 __set() 方法来访问它。 当对象的成员/属性被修改或添加时,“Storable”类会注意到这一点。 当访问 Storable 类上的属性时,Storable 类上的 __get() 返回该属性,包装在另一个 Storable 类中,以便也可以针对每个新级别递归地跟踪该属性的更改。

问题在于对象不再是本机数据类型,因此您无法在数组上运行数组函数。

例如:

$storage = new Storage();

var_dump($storage->object); // array('a', 'b')

array_push($storage->object, 'c'); // fails

因此,我们必须将这些数组函数实现为 Storable 的方法。

例如:

$storage = new Storage();

var_dump($storage->object); // array('a', 'b')

$storage->object->push('c');

这一切都很好,但我想知道是否可以以某种方式使用本机函数,以减少我正在开发的库的开销,同时跟踪更改,以便将任何更改添加到持久存储中。

2)忘记跟踪更改,只需更新整个对象结构

这是使程序中的对象与实际存储在对象缓存中的对象保持同步的最简单方法(可以位于不同的对象上)机器)。

然而,这意味着当单个索引发生变化时,整个结构(例如具有 1000 个索引的数组)必须通过套接字发送到对象缓存。

3)在本地保留对象的镜像

我还尝试过克隆该对象,并保持克隆对象不变。 然后,当 PHP 脚本完成所有处理后,递归地将克隆与修改后的对象进行比较,并将更改的属性提交回对象缓存。

然而,这需要下载整个对象才能使用它。 它还要求对象占用两倍的内存,因为它是克隆的。


我知道这很模糊,但是涉及大量代码。 如果有人想查看代码,我可以将其发布,或者将其放在开放的 SVN 存储库上。 该项目是开源的,但我还没有建立公共存储库。

I'm trying to track all changes made to a PHP variable. The variable can be an object or array.

For example it looks something like:

$object = array('a', 'b');

This object is then persisted to storage using an object-cache. When php script runs again.

So when the script runs the second time, or another script runs and modifies that object, I want those modifications to be tracked, either as they are being done, or in one go after the script executes.

eg:

$object[] = 'c';

I would like to know that 'c' was added to the object.

Now the actually code looks something like this:

$storage = new Storage();
$storage->object = array('a', 'b');

second load:

$storage = new Storage();

var_dump($storage->object); // array('a', 'b')

$storage->object[] = 'c';

What I want to know is that 'c' was pushed into $storage->object so in the class "Storage" I can set that value to persistent storage.

I have tried a few methods, that work, but have downsides.

1) Wrap all objects in a class "Storable" which tracks changes to the object

The class "Storable" just saves the actual data object as a property, and then provides __get() and __set() methods to access it. When a member/property of the object is modified or added, the "Storable" class notes this.
When a a property is accessed __get() on the Storable class returns the property, wrapped in another Storable class so that changes on that are tracked also, recursively for each new level.

The problem is that the objects are no longer native data types, and thus you cannot run array functions on arrays.

eg:

$storage = new Storage();

var_dump($storage->object); // array('a', 'b')

array_push($storage->object, 'c'); // fails

So instead we'd have to implement these array functions as methods of Storable.

eg:

$storage = new Storage();

var_dump($storage->object); // array('a', 'b')

$storage->object->push('c');

This is all good, but I'd like to know if its possible to somehow use native functions, to reduce the overhead on the library I'm developing, while tracking changes so any changes can be added to persistent storage.

2) Forget about tracking changes, and just update whole object structures

This is the simplest method of keeping the objects in the program synchronized with the objects actually stored in the object-cache (which can be on a different machine).

However, it means whole structures, like an array with 1000 indexes, have to be sent though a socket to the object-cache when a single index changes.

3) Keep a mirror of the object locally

I've also tried cloning the object, and keeping a clone object untouched. Then when all processing is done by the PHP script, compare the clone to the modified object recursively, and submitting changed properties back to the object-cache.

This however requires that the whole object be downloaded in order to use it.
It also requires that the object take up twice as much memory, since it is cloned.


I know this is pretty vague, but there is a quite a bit of code involved. If anyone wants to see the code I can post it, or put it up on an open SVN repo. The project is open source but I haven't set up a public repository yet.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

南城旧梦 2024-08-08 14:36:01

由于您的“对象”实际上是一个数组,因此您无法向其添加功能。 您用类方法封装它的想法是正确的方法。 在这个阶段,担心性能而不是正确的设计是无关紧要的,而且是误导性的——使用这种方法所产生的开销对于您的整体应用程序性能来说可能微不足道。

您应该查看 SPL 数组类,例如 ArrayObject 。 它们提供了完整的类似数组的接口并且易于扩展。

Since your 'object' is really an array, you can't add functionality to it. Your idea of encapsulating it with class methods is the correct approach. Worrying about performance over proper design at this stage is irrelevant and misguided - the overhead you incur with this approach will likely be insignificant to your overall application performance.

You should look into the SPL array classes such as ArrayObject. They provide a complete array-like interface and are easily extendable.

跨年 2024-08-08 14:36:01

老实说,我会重新考虑你在做什么。 您确实试图将 PHP 变成它不是的东西。 这是您在 Java 和 C# 而不是 PHP 中看到的那种 ORM,它本质上基本上是瞬态的(这意味着除了 memcache/APC/etc 之外的所有内容都会在每个请求上重新创建)。 这是对复杂的对象缓存和更改跟踪的厌恶。

话虽这么说,你能做到这一点的唯一方法是将所有内容包装在重载 __get()__set()__isset() 的东西中并实现 ArrayAccess

In all honesty I would reconsider what you're doing. You're really trying to turn PHP into something it's not. This is the kind of ORM you see in Java and C# not PHP, which is basically transient in nature (meaning everything, barring memcache/APC/etc, is recreated on each request). This is anathema to sophisticated object caching and change tracking.

That being said, the only way you could do this is wrap everything in something that overloads __get(), __set() and __isset() and implements ArrayAccess.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文