lox / pheasant

A lightweight data mapper designed to take advantage of PHP 5.3+
http://getpheasant.com
MIT License
101 stars 21 forks source link

Updating properties in 'remote' DomainObject is broken #79

Closed bjornpost closed 10 years ago

bjornpost commented 10 years ago

I guess the testcase is clear :-).

.....................................................F

Time: 3.54 seconds, Memory: 11.50Mb

There was 1 failure:

1) Pheasant\Tests\DomainObjectTest::testReadingRemoteProperty
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'Elastigirl'
+'Mr. Incredible'
lox commented 10 years ago

Pheasant doesn't maintain any internal identity maps. A call to a relationship will always return a brand new object. The new with() support will still maintain this contract, it will just cache the source data within the collection to prevent multiple queries being fired.

bjornpost commented 10 years ago

Is this something we would like to solve? Otherwise I'd say this is something that needs a place in the documentation.

lox commented 10 years ago

Yup, I think this needs to be very clearly documented. Alternately, it's possible we could accomplish this behavior with a per-relationship cache.

bjornpost commented 10 years ago

A cache might be a good thing, as we don't cache relationships before sending them to our templates. This currently results in a lot of unnecessary trips to the database:

// in controller
$p = \Model\Project::byId(1234);

// in our template (example):
{{ p.id }} {{ p.name }}  - {{ p.Client.id }} {{ p.Client.name }}
lox commented 10 years ago

I believe that the with() caching in 1.3 will solve this problem for you. Feel free to re-open if it doesn't.

Jud commented 10 years ago

I'd like to reopen this, as it seems like the intended behavior in this issue is actually happening. We have two domain objects Credit and CreditProduct, in a typical hasMany and belongsTo relationship.

Suppose CreditProduct #1 belongsTo Credit #1. The following observed behavior seems to contradict this thread:

# In CreditProduct afterSave, we save the credit to bust caches, etc
# function afterSave(){
#   $this->credit->save();
# }

# In a controller:
$credit = Credit::find(1);
$credit->reason = "Hello";
$credit_product = CreditProduct::create(array(
  'credit_id' => $credit->id,
  'product_id' => 2,
));

# "Hello" has been saved to the db as the credit reason,
# even though the afterSave function in CreditProduct should get a new instance.