I am seeing an unexpected caching effect in Doctrine (1.2.4).
I have a couple of related tables defined by the following YAML (several additional fields not used in the example removed). Just a simple 1-Many relationship from students to schools.
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
I can create a simple Doctrine (1.2.4) query to get back a student with
$result1 = Doctrine_Query::create()
->from('Student s')
->where('s.id = 1')
->execute();
and then extract out the corresponding school name with
foreach ($result1 as $result) { $ans[] = $result->School["name"]; }
I now modify the school_id (that causes the relationship) by following this with:
foreach ($result1 as $result)
{ $result["school_id"] = 1 - $result["school_id"]; $result->save(); }
(I have set up the DB so that this gives another valid school ID).
If I were to now, immediately, try to access the relationship I will get the old school's name. I understand this - it is because I've not called refreshRelated(). What I find unexpected is that if I immediately make another query duplicating the first
$result2 = Doctrine_Query::create()
->from('Student s')
->where('s.id = 1')
->execute();
and get its result
foreach ($result2 as $result) { $ans[] = $result->School["name"]; }
when I examine the contents of my array I find that, in both cases, I have the same school name. In other words, even though I've done a second query and am looking at the result of the query the relationship is not refreshed.
The data in the database is fine and consistent; i.e. appropriate students and schools exist. E.g. running the above sequence a second time - in a different program execution - uses the other school name (although again duplicated).
Where is this caching coming from?
Doctrine use a little caching on the relations : your Student->School
is stored into a Student
attribute, and your Student->school_id
too, in another attribute.
When you change your Student->school_id
, the database get queryied, and the Student->school_id
change, but the Student->School
doesn't, as rehydrating this object might be CPU/memory expansive.
Doctrine provide some method to refresh the relations, but it's the developper's responsability to use it.
Example :
$student->refreshRelated('School'); //refreshes only the School relation
$student->refreshRelated(); //refreshes every relation of the $student
But there's another caching. Doctrine keeps all the hydrated object in memory, in order to limit the request number. So when you query again for your student, you find that your Student->School
hasn't changed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With