From 95a123bacaad0e7c1352ddce93f26c1313e2675d Mon Sep 17 00:00:00 2001 From: Mathieu TUDISCO Date: Thu, 15 Jun 2017 11:22:21 +0200 Subject: [PATCH 1/3] Add fresh method on Eloquent/Collection. --- .../Database/Eloquent/Collection.php | 13 ++++++++++++- .../DatabaseEloquentCollectionTest.php | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/Illuminate/Database/Eloquent/Collection.php b/src/Illuminate/Database/Eloquent/Collection.php index 16fb1a484278..f5325b56418e 100755 --- a/src/Illuminate/Database/Eloquent/Collection.php +++ b/src/Illuminate/Database/Eloquent/Collection.php @@ -127,7 +127,7 @@ public function merge($items) * Run a map over each of the items. * * @param callable $callback - * @return \Illuminate\Support\Collection + * @return \Illuminate\Support\Collection|static */ public function map(callable $callback) { @@ -138,6 +138,17 @@ public function map(callable $callback) }) ? $result->toBase() : $result; } + /** + * Reload a fresh model instance from the database for all the entities. + * + * @param array|string $with + * @return static + */ + public function fresh($with = []) + { + return $this->map->fresh($with); + } + /** * Diff the collection with the given items. * diff --git a/tests/Database/DatabaseEloquentCollectionTest.php b/tests/Database/DatabaseEloquentCollectionTest.php index a5f6e556bcca..1884fdf6f51d 100755 --- a/tests/Database/DatabaseEloquentCollectionTest.php +++ b/tests/Database/DatabaseEloquentCollectionTest.php @@ -212,6 +212,24 @@ public function testMap() $this->assertInstanceOf(Collection::class, $cAfterMap); } + public function testFresh() + { + $one = m::mock('Illuminate\Database\Eloquent\Model'); + $oneFresh = m::mock('Illuminate\Database\Eloquent\Model'); + $one->shouldReceive('fresh')->andReturn($oneFresh); + + $two = m::mock('Illuminate\Database\Eloquent\Model'); + $twoFresh = m::mock('Illuminate\Database\Eloquent\Model'); + $two->shouldReceive('fresh')->andReturn($twoFresh); + + $c = new Collection([$one, $two]); + + $cAfterFresh = $c->fresh(); + + $this->assertEquals(new Collection([$oneFresh, $twoFresh]), $cAfterFresh); + $this->assertInstanceOf(Collection::class, $cAfterFresh); + } + public function testMappingToNonModelsReturnsABaseCollection() { $one = m::mock('Illuminate\Database\Eloquent\Model'); From ff707c831e5180cdb0ff7246dd4f9d9dd51db4d0 Mon Sep 17 00:00:00 2001 From: Mathieu TUDISCO Date: Thu, 15 Jun 2017 16:06:28 +0200 Subject: [PATCH 2/3] Rewrite completely the method to avoid multiple database calls. Add full tests for Model::fresh() and Collection::fresh() methods. --- .../Database/Eloquent/Collection.php | 12 +++++- .../DatabaseEloquentCollectionTest.php | 18 -------- .../DatabaseEloquentIntegrationTest.php | 42 +++++++++++++++++++ 3 files changed, 53 insertions(+), 19 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/Collection.php b/src/Illuminate/Database/Eloquent/Collection.php index f5325b56418e..45c80ee92724 100755 --- a/src/Illuminate/Database/Eloquent/Collection.php +++ b/src/Illuminate/Database/Eloquent/Collection.php @@ -146,7 +146,17 @@ public function map(callable $callback) */ public function fresh($with = []) { - return $this->map->fresh($with); + $model = $this->first(); + + $freshModels = $model->newQueryWithoutScopes() + ->with(is_string($with) ? func_get_args() : $with) + ->whereIn($model->getKeyName(), $this->modelKeys()) + ->get() + ->getDictionary(); + + return $this->map(function ($model) use ($freshModels) { + return $model->exists ? $freshModels[$model->getKey()] : null; + }); } /** diff --git a/tests/Database/DatabaseEloquentCollectionTest.php b/tests/Database/DatabaseEloquentCollectionTest.php index 1884fdf6f51d..a5f6e556bcca 100755 --- a/tests/Database/DatabaseEloquentCollectionTest.php +++ b/tests/Database/DatabaseEloquentCollectionTest.php @@ -212,24 +212,6 @@ public function testMap() $this->assertInstanceOf(Collection::class, $cAfterMap); } - public function testFresh() - { - $one = m::mock('Illuminate\Database\Eloquent\Model'); - $oneFresh = m::mock('Illuminate\Database\Eloquent\Model'); - $one->shouldReceive('fresh')->andReturn($oneFresh); - - $two = m::mock('Illuminate\Database\Eloquent\Model'); - $twoFresh = m::mock('Illuminate\Database\Eloquent\Model'); - $two->shouldReceive('fresh')->andReturn($twoFresh); - - $c = new Collection([$one, $two]); - - $cAfterFresh = $c->fresh(); - - $this->assertEquals(new Collection([$oneFresh, $twoFresh]), $cAfterFresh); - $this->assertInstanceOf(Collection::class, $cAfterFresh); - } - public function testMappingToNonModelsReturnsABaseCollection() { $one = m::mock('Illuminate\Database\Eloquent\Model'); diff --git a/tests/Database/DatabaseEloquentIntegrationTest.php b/tests/Database/DatabaseEloquentIntegrationTest.php index 028b149572f5..b1fe13b3686b 100644 --- a/tests/Database/DatabaseEloquentIntegrationTest.php +++ b/tests/Database/DatabaseEloquentIntegrationTest.php @@ -1069,6 +1069,48 @@ public function testIsAfterRetrievingTheSameModel() $this->assertTrue($saved->is($retrieved)); } + public function testFreshMethodOnModel() + { + \Carbon\Carbon::setTestNow('now'); + $now = \Carbon\Carbon::getTestNow(); + + $storedUser1 = EloquentTestUser::create(['id' => 1, 'email' => 'taylorotwell@gmail.com']); + $storedUser1->newQuery()->update(['email' => 'dev@mathieutu.ovh', 'name' => 'Mathieu TUDISCO']); + $freshStoredUser1 = $storedUser1->fresh(); + + $storedUser2 = EloquentTestUser::create(['id' => 2, 'email' => 'taylorotwell@gmail.com']); + $storedUser2->newQuery()->update(['email' => 'dev@mathieutu.ovh']); + $freshStoredUser2 = $storedUser2->fresh(); + + $notStoredUser = new EloquentTestUser(['id' => 3, 'email' => 'taylorotwell@gmail.com']); + $freshNotStoredUser = $notStoredUser->fresh(); + + $this->assertEquals(['id' => 1, 'email' => 'taylorotwell@gmail.com', 'created_at' => $now, 'updated_at' => $now], $storedUser1->toArray()); + $this->assertEquals(['id' => 1, 'name' => 'Mathieu TUDISCO', 'email' => 'dev@mathieutu.ovh', 'created_at' => $now, 'updated_at' => $now], $freshStoredUser1->toArray()); + $this->assertInstanceOf(EloquentTestUser::class, $storedUser1); + + $this->assertEquals(['id' => 2, 'email' => 'taylorotwell@gmail.com', 'created_at' => $now, 'updated_at' => $now], $storedUser2->toArray()); + $this->assertEquals(['id' => 2, 'name' => null, 'email' => 'dev@mathieutu.ovh', 'created_at' => $now, 'updated_at' => $now], $freshStoredUser2->toArray()); + $this->assertInstanceOf(EloquentTestUser::class, $storedUser2); + + $this->assertEquals(['id' => 3, 'email' => 'taylorotwell@gmail.com'], $notStoredUser->toArray()); + $this->assertEquals(null, $freshNotStoredUser); + } + + public function testFreshMethodOnCollection() + { + EloquentTestUser::create(['id' => 1, 'email' => 'taylorotwell@gmail.com']); + EloquentTestUser::create(['id' => 2, 'email' => 'taylorotwell@gmail.com']); + + $users = EloquentTestUser::all() + ->add(new EloquentTestUser(['id' => 3, 'email' => 'taylorotwell@gmail.com'])); + + EloquentTestUser::find(1)->update(['name' => 'Mathieu TUDISCO']); + EloquentTestUser::find(2)->update(['email' => 'dev@mathieutu.ovh']); + + $this->assertEquals($users->map->fresh(), $users->fresh()); + } + /** * Helpers... */ From 7cd6ae22b799b731e7c75a499420247afbeb9ec0 Mon Sep 17 00:00:00 2001 From: Mathieu TUDISCO Date: Thu, 15 Jun 2017 16:44:58 +0200 Subject: [PATCH 3/3] Update tests for php5.6 and Carbon v1.20.0 --- tests/Database/DatabaseEloquentIntegrationTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Database/DatabaseEloquentIntegrationTest.php b/tests/Database/DatabaseEloquentIntegrationTest.php index b1fe13b3686b..c72960e4ba27 100644 --- a/tests/Database/DatabaseEloquentIntegrationTest.php +++ b/tests/Database/DatabaseEloquentIntegrationTest.php @@ -1071,8 +1071,8 @@ public function testIsAfterRetrievingTheSameModel() public function testFreshMethodOnModel() { - \Carbon\Carbon::setTestNow('now'); - $now = \Carbon\Carbon::getTestNow(); + $now = \Carbon\Carbon::now(); + \Carbon\Carbon::setTestNow($now); $storedUser1 = EloquentTestUser::create(['id' => 1, 'email' => 'taylorotwell@gmail.com']); $storedUser1->newQuery()->update(['email' => 'dev@mathieutu.ovh', 'name' => 'Mathieu TUDISCO']);