Есть ли более собственный способ (например, встроенная функция) с меньшим кодом пользователя, чтобы проверить, изменились ли значения свойств объектов вместо одного из этих методов:
Сериализованный подход
$obj = new stdClass(); // May be an instance of any class echo $hashOld = md5(serialize($obj)) . PHP_EOL; $obj->change = true; echo $hashNew = md5(serialize($obj)) . PHP_EOL; echo 'Changed: '; var_dump($hashOld !== $hashNew);
Результат:
f7827bf44040a444ac855cd67adfb502 (initial) 506d1a0d96af3b9920a31ecfaca7fd26 (changed) Changed: bool(true)
Подход теневой копии
$obj = new stdClass(); $shadowObj = clone $obj; $obj->change = true; var_dump($shadowObj != $obj);
Результат:
bool(true);
Оба подхода работают. Но оба они имеют недостатки по сравнению с реализацией, не связанной с пользователем. Первому нужен процессор для сериализации и хеширования, а второй нужен для хранения клонов. И некоторые классы не могут быть клонированы.
Не отслеживает ли PHP изменения в свойствах объекта? И PHP не предоставляет метод, чтобы использовать его?
Что вы пытаетесь сделать?
Вы пытаетесь сравнить объект с самим собой, после некоторой цепочки «неизвестных» операций, чтобы проверить, изменился ли объект. Если это так, есть некоторые логические точки для наблюдения. Сначала, если вы хотите сравнить объект с самим собой, у вас есть только два варианта:
Другого логического подхода нет. Сравнение распределений памяти, реальных объектов, копирование объектов, сравнение хэшей – все в первой. Отслеживание изменений, сохранение изменений внутри объекта, одновременное запоминание операций, внутри точки 2.
Поэтому, на мой взгляд, этот вопрос является своего рода резервной копией данных. В этом случае существует много и много решений, но ни один из них не жестко закодирован внутри php, насколько мне известно. Зачем?
Ответ прост. У парней PHP есть те же проблемы, что у вас есть :). Поскольку, если это было бы затруднено внутри php, то php должен запускать / использовать один из этих механизмов (1) или (2).
В этом случае каждый созданный вами объект и каждая сделанная вами операция должны быть записаны где-то, чтобы запомнить каждое состояние / объект / что-то и использовать их для сравнения в будущем.
Хотя вам нужно это решение, почти на ~100%
сайтов нет. Таким образом, жесткая кодировка этого внутреннего php заставит ~100%
веб-сайтов работать медленнее, а ваша работа будет быстрее;).
Единственное решение (возможно, встроенное в php в будущем), которое я могу представить, – это сделать какой-то флагом конфигурации php: track objects
, и только если этот флаг является true
, тогда запустите все механизмы php отслеживания состояний объектов. Но это также означает огромный разрыв в производительности. Как и все ifs
(если отслеживание, если отслеживание, если отслеживание), также являются временем обработки и памяти.
Есть и проблема, что сравнивать? Вам нужно сравнить объект с тем же объектом, но … Несколько минут назад? Несколько операций назад? Нет … Вы должны указать ровно одно место в коде, а затем указать второе место в коде и сравнить объект в этих двух местах. Таким образом, гипотетическое автоматическое отслеживание … Тип бессильного, так как нет «ключа» в состоянии состояния массива времени . Я имею в виду, даже если у вас есть функция magic_object_comparer
, как она должна выглядеть?
<?php function magic_object_comparer() {} // Arguments?? function magic_object_comparer($object_before, $object_after) {} // you must save object_before somewhere...?? function magic_object_comparer($object, $miliseconds) {} // How many miliseconds? function magic_object_comparer($object, $operations) {} // How many operations? Which operations? magic_comparer_start($object); // ... Few operations... $boolean = magic_comparer_compare_from start($object); // Same as own implementation... ?>
В конце концов, я бы предложил реализовать для этого какой-то собственный механизм и не забудьте использовать его только там, где он вам нужен. Поскольку этот механизм наверняка будет потреблять время и память. Поэтому подумайте внимательно:
И после всего этого попытайтесь его реализовать. Я вижу, что у вас есть огромное знание php, поэтому я уверен, что вы что-то придумаете. В этом вопросе и обсуждении есть много комментариев и возможных идей.
Но в конце концов, может быть, я немного объяснил, почему нет решения для сборки, и почему в будущем не должно быть такого … :).
Взгляните сюда: http://www.fluffycat.com/PHP-Design-Patterns/ . Это отличный ресурс о шаблонах PHP. Вы должны взглянуть на модели адаптеров , декораторов и наблюдателей для возможных элегантных объектно-ориентированных решений.
Хотя я тоже ищу очень быстрый / быстрый подход, вариант метода 2 – это то, что я использую. Преимущество этого метода в том, что он (довольно) быстрый (по сравнению с isset ()), в зависимости от размера объекта. И вам не нужно помнить, что каждый раз, когда вы меняете объект, устанавливаете свойство ->modified
.
global $shadowcopy; // just a single copy in this simple example. $thiscopy = (array) $obj; // don't use clone. if ($thiscopy !== $shadowcopy) { // it has been modified // if you want to know if a field has been added use array_diff_key($thiscopy,$shadowcopy); } $shadowcopy = $thiscopy; // if you don't modify thiscopy or shadowcopy, it will be a reference, so an array copy won't be triggered.
Это в основном метод 2, но без клона. Если ваше значение свойства – это другой объект (vobj), тогда может понадобиться клонировать (в противном случае обе ссылки указывают на один и тот же объект), но тогда стоит отметить, что именно этот объект vobj вы хотите увидеть, если он изменился с помощью вышеописанного код. Дело в клоне заключается в том, что он создает второй объект (аналогичная производительность), но если вы хотите увидеть, какие значения изменились, вам не нужен сам объект, только значения. И массив casting объекта очень быстр (~ 2x скорость булевского литья bool) .. ну, до больших объектов. Прямое сравнение массива === очень быстрое, для массивов, скажем, 100 vals.
Я уверен, что существует еще более быстрый метод …
Боюсь, нет встроенного метода. Подход теневой копии – лучший способ.
Более простой способ, если у вас есть контроль над классом, заключается в добавлении modified
переменной:
$this->modified = false;
Когда я каким-либо образом изменяю объект, я просто использую
$obj->modified = true;
Таким образом, я могу позже проверить
if($obj->modified){ // Do Something
чтобы проверить, было ли оно изменено. Просто не забудьте unset($obj->modified)
перед сохранением содержимого в базе данных.