morris/lessql

Correct approach to update objects and its N:N relationship

allysson-david opened this issue · 4 comments

Issue happens when trying to use $row->setData($array) to update one of the objects and its relationships.
Consider that I have three tables: first, second and first_second used for the N:N relationship.

First thing I did was set the composite key for the N:N relationship table:
$db->setPrimary('first_second', array('first_id', 'second_id'));

Assume first and second both have two rows each, with their ids being 1 and 2.
Assume first_second has 3 rows:

first_id second_id
1 1
1 2
2 1

So here I am, running this code:

$first_one = $db->first(1);
$second_two = $db->second(2);

$data = [
    'value' => 'changed something',
    'first_secondList' => [
        [
            'second' => $second_two,
        ],
    ],
];

$first_one->setData($data);
$first_one->save();

I expected it to break my relationship between first.id = 1 and second.id = 1 since I ommited it. Instead of it LessQL is trying to re-insert the relationship between first.id = 1 and second.id = 2 causing an error, here's the following output found after setting the callback to print the queries:

SELECT * FROM `first` WHERE `id` = '1'
SELECT * FROM `second` WHERE `id` = '2'
UPDATE `first` SET `value` = 'changed something' WHERE `id` = '1'
INSERT INTO `first_second` ( `first_id`, `second_id` ) VALUES ( '1', '2' )

Should I assume that the expected procedure is to delete all relationships first and re-set them?
Shouldn't it at least not try to insert an already existing object?
I got as far as figuring that the first_secondList object is treated as a new one because its $_originalId is empty and save() tries to insert it again after exists() returns false, but I have no idea why that isn't correctly filled.

Thanks in advance.

So it seems that $_originalId is empty because a new object is created when __set() (Row.php) finds I'm adding a column ending with 'List' and uses createRow() instead of finding the right object.
Now I'm thinking about how I should go about that.

Should I assume that the expected procedure is to delete all relationships first and re-set them?

Please reffer to: #45

If I include $first_one->first_secondList()->delete() before $first_one->setData($data) it will trigger the error I mentioned previously (if $first_one object didn't have any relationship with second table), which is why I assumed something was wrong with this approach, but dunno.

Good catch. Yeah #45 is a show stopper here, there's no workaround except querying before deleting :o sorry!

Fixed in #45