Search code examples
phpforeign-keyspropel

Why does a related Propel object get a preUpdate hook call?


I have noticed a strange behaviour when intercepting the preUpdate row hook in Propel (1.6.1). Consider this schema:

<?xml version="1.0" encoding="UTF-8"?>
<database name="test" defaultIdMethod="native" baseClass="MyBaseObject">
    <table name="test_event">
        <column name="id" type="integer" required="true" primaryKey="true" autoIncrement="true" />
        <column name="name" type="varchar" size="50" required="true" />
        <column name="description" type="varchar" size="250" />
        <column name="location" type="varchar" size="250" />
        <column name="nearest_city" type="varchar" size="100" />
        <column name="start_time" type="timestamp" />
        <column name="duration_mins" type="integer" />
        <column name="organiser_id" type="integer" required="true" />
        <foreign-key foreignTable="test_organiser">
            <reference local="organiser_id" foreign="id" />
        </foreign-key>
    </table>

    <table name="test_organiser">
        <column name="id" type="integer" required="true" primaryKey="true" autoIncrement="true" />
        <column name="name" type="varchar" size="50" required="true" />     
        <column name="email" type="varchar" size="100" />
    </table>
</database>

I've noticed that an update to TestOrganiser results in two preUpdate calls to the custom class - one for itself and one for TestEvent. However, if the first table is updated, only itself gets a preUpdate call. Why is this?

Edit: earlier I added my own answer. However if anyone would like to add further detail, please do - the more clarity the better! If an update is made to test_organiser, in what sense can test_event be said to be updating, especially since it is marked as unmodified?


Solution

  • I typed out most of this question, and then worked it out for myself! I thought I would add the q anyway, as I think it is of general interest.

    I'd initially thought that TestEvent ought to get the two calls - one for itself, and one for its dependent object. But a save to TestEvent doesn't affect TestOrganiser, since the relation goes out from test_event to test_organiser.

    So, the Propel behaviour is correct; since test_organiser is dependent on test_event, both are notified if the former is modified. This can be thought of like a non-hierarchical parent-child relation (test_event has the foreign key, so that is the 'parent').

    My solution to filtering out related row notifications of this kind (and non-modified rows generally) is simply to do this in the custom row ancestor class:

        public function preUpdate(PropelPDO $con = null)
        {
            // Ignore (related) rows with no changes
            if (!$this->isModified())
            {
                return true;
            }
    
            // Rest of handling code here...
        }