Отслеживание изменений свойств объекта PHP

Я пытаюсь отследить все изменения, внесенные в переменную 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" это замечает. При обращении к свойству __get() класса Storable возвращает свойство, обернутое в другой класс 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. Проект с открытым исходным кодом, но я еще не создал публичный репозиторий.

2 ответа

Решение

Поскольку ваш "объект" действительно массив, вы не можете добавить к нему функциональность. Ваша идея инкапсулировать его с помощью методов класса - правильный подход. Беспокойство о производительности по сравнению с правильным дизайном на данном этапе не имеет значения и вводит в заблуждение - накладные расходы, которые вы несете с этим подходом, вероятно, будут незначительными для общей производительности вашего приложения.

Вы должны посмотреть на классы массива SPL, такие как ArrayObject. Они обеспечивают полный интерфейс в виде массива и легко расширяются.

Честно говоря, я бы пересмотрел то, что вы делаете. Вы действительно пытаетесь превратить PHP в то, чем это не является. Это тот тип ORM, который вы видите в Java и C#, а не в PHP, который в основном временный (то есть все, за исключением memcache/APC/etc, воссоздается при каждом запросе). Это анафема для сложного кеширования объектов и отслеживания изменений.

Это, как говорится, единственный способ сделать это - обернуть все в то, что перегружает __get(), __set() а также __isset() и реализует ArrayAccess,

Другие вопросы по тегам