Intereting Posts
Как получить все после определенного персонажа? Удаление части пути в php Ошибка модуля входа: свойство «LoginForm._id» не определено mySQL выбирает zipcodes в пределах x км / миль в пределах диапазона y Упростите цикл через массив, который может быть плоским или многомерным Несколько действий.class.php Laravel 4 – общедоступный каталог обрабатывается как маршрут – изображение не отображается как преобразовать японский английский характер нормальному английскому персонажу? Как получить текущий URL-адрес, а затем получить последние слова токен сеанса не устанавливается в первый раз Как сделать интеграцию входа в facebook на веб-сайте magento? Элементы подсчета в каждом вспомогательном массиве в php Как получить доступ к переменной с включенной страницы? Как получить имя файла под папкой? Получить данные из таблицы базы данных MySQL по определенному полю в URL-адресе

Проверьте, изменился ли объект

Есть ли более собственный способ (например, встроенная функция) с меньшим кодом пользователя, чтобы проверить, изменились ли значения свойств объектов вместо одного из этих методов:

Сериализованный подход

$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 не предоставляет метод, чтобы использовать его?

Что вы пытаетесь сделать?

Вы пытаетесь сравнить объект с самим собой, после некоторой цепочки «неизвестных» операций, чтобы проверить, изменился ли объект. Если это так, есть некоторые логические точки для наблюдения. Сначала, если вы хотите сравнить объект с самим собой, у вас есть только два варианта:

  1. Помните все состояние объекта (например, хеш или просто скопируйте весь объект)
  2. Отслеживание изменений с течением времени

Другого логического подхода нет. Сравнение распределений памяти, реальных объектов, копирование объектов, сравнение хэшей – все в первой. Отслеживание изменений, сохранение изменений внутри объекта, одновременное запоминание операций, внутри точки 2.

Поэтому, на мой взгляд, этот вопрос является своего рода резервной копией данных. В этом случае существует много и много решений, но ни один из них не жестко закодирован внутри php, насколько мне известно. Зачем?


Ответ прост. У парней PHP есть те же проблемы, что у вас есть :). Поскольку, если это было бы затруднено внутри php, то php должен запускать / использовать один из этих механизмов (1) или (2).

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

Хотя вам нужно это решение, почти на ~100% сайтов нет. Таким образом, жесткая кодировка этого внутреннего php заставит ~100% веб-сайтов работать медленнее, а ваша работа будет быстрее;).


PHP гипотетическое решение?

Единственное решение (возможно, встроенное в 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... ?> 

К сожалению, вы остаетесь с собственной реализацией …

В конце концов, я бы предложил реализовать для этого какой-то собственный механизм и не забудьте использовать его только там, где он вам нужен. Поскольку этот механизм наверняка будет потреблять время и память. Поэтому подумайте внимательно:

  1. Какие объекты вы хотите сравнить. Зачем?
  2. Когда вы хотите их сравнить?
  3. Нужно ли сравнивать все изменения?
  4. Каков самый простой способ сэкономить изменения этих состояний?

И после всего этого попытайтесь его реализовать. Я вижу, что у вас есть огромное знание 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) перед сохранением содержимого в базе данных.