Я вижу неожиданный эффект кеширования в Доктрине (1.2.4).
У меня есть пара связанных таблиц, определенных следующим YAML (несколько дополнительных полей, которые не используются в примере, удалены). Просто простые отношения «1-Много» от студентов к школам.
School: tableName: tblschool columns: sch_id: name: sch_id as id primary: true autoincrement: true type: integer(4) sch_name: name: sch_name as name type: string(50) Student: tableName: tblstudent columns: stu_id: name: stu_id as id primary: true autoincrement: true type: integer(4) stu_sch_id: name: stu_sch_id as school_id type: integer(4) relations: School: local: school_id foreign: id foreignAlias: Students
Я могу создать простой запрос Doctrine (1.2.4), чтобы вернуть ученика с
$result1 = Doctrine_Query::create() ->from('Student s') ->where('s.id = 1') ->execute();
а затем извлеките соответствующее название школы с помощью
foreach ($result1 as $result) { $ans[] = $result->School["name"]; }
Теперь я изменяю school_id (который вызывает отношения), следуя этому:
foreach ($result1 as $result) { $result["school_id"] = 1 - $result["school_id"]; $result->save(); }
(Я создал БД так, чтобы это дало еще один действительный идентификатор школы).
Если бы я был сейчас, немедленно, попытайтесь получить доступ к отношениям, я получу имя старой школы. Я это понимаю – это потому, что я не вызвал refreshRelated (). То, что я нахожу неожиданным, состоит в том, что если я немедленно сделаю другой запрос, дублирующий первый
$result2 = Doctrine_Query::create() ->from('Student s') ->where('s.id = 1') ->execute();
и получить его результат
foreach ($result2 as $result) { $ans[] = $result->School["name"]; }
когда я просматриваю содержимое своего массива, я нахожу, что в обоих случаях у меня одно и то же имя школы. Другими словами, хотя я сделал второй запрос и смотрю на результат запроса, связь не обновляется.
Данные в базе данных являются точными и согласованными; т.е. существуют соответствующие ученики и школы. Например, выполнение указанной последовательности второй раз – при выполнении другой программы – использует другое название школы (хотя повторное дублирование).
Откуда это кэширование?
Доктрина использует небольшое кэширование в отношениях: ваша Student->School
хранится в атрибуте Student
, а ваш Student->school_id
тоже в другом атрибуте.
Когда вы меняете свой Student->school_id
, Student->school_id
базу данных, а Student->school_id
, а Student->School
– нет, так как регидратация этого объекта может быть расширением CPU / memory.
Doctrine предоставляет некоторый метод для обновления отношений , но это способность разработчика использовать его.
Пример :
$student->refreshRelated('School'); //refreshes only the School relation $student->refreshRelated(); //refreshes every relation of the $student
-$student->refreshRelated('School'); //refreshes only the School relation $student->refreshRelated(); //refreshes every relation of the $student
Но есть еще одно кэширование. Doctrine хранит все гидратированные объекты в памяти, чтобы ограничить номер запроса. Поэтому, когда вы снова запрашиваете своего ученика, вы обнаружите, что ваша Student->School
не изменилась.