From 50c8ce1a5bd51fdf9b07c6117471cd806a13c393 Mon Sep 17 00:00:00 2001 From: overtrue Date: Thu, 4 Nov 2021 11:31:03 +0800 Subject: [PATCH] Added orderByFollowersCount*() methods. --- README.md | 14 ++++++++++++ src/Followable.php | 15 +++++++++++++ tests/FeatureTest.php | 50 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 77 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dc4aed0..2030222 100644 --- a/README.md +++ b/README.md @@ -207,6 +207,20 @@ $user->attachFollowStatus($users); ``` +### Order by followers count + +You can query users order by followers count with following methods: + +- `orderByFollowersCountDesc()` +- `orderByFollowersCountAsc()` +- `orderByFollowersCount(string $direction = 'desc')` + +example: + +```php +$users = User::orderByFollowersCountDesc()->get(); +$mostPopularUser = User::orderByFollowersCountDesc()->first(); +``` ### N+1 issue diff --git a/src/Followable.php b/src/Followable.php index b7495da..861b875 100644 --- a/src/Followable.php +++ b/src/Followable.php @@ -146,6 +146,21 @@ public function areFollowingEachOther($user): bool return $this->isFollowing($user) && $this->isFollowedBy($user); } + public function scopeOrderByFollowersCount($query, string $direction = 'desc') + { + return $query->withCount('followers')->orderBy('followers_count', $direction); + } + + public function scopeOrderByFollowersCountDesc($query) + { + return $this->scopeOrderByFollowersCount($query, 'desc'); + } + + public function scopeOrderByFollowersCountAsc($query) + { + return $this->scopeOrderByFollowersCount($query, 'asc'); + } + public function followers(): \Illuminate\Database\Eloquent\Relations\BelongsToMany { /* @var \Illuminate\Database\Eloquent\Model $this */ diff --git a/tests/FeatureTest.php b/tests/FeatureTest.php index 32123e9..346a4f1 100644 --- a/tests/FeatureTest.php +++ b/tests/FeatureTest.php @@ -216,7 +216,53 @@ function () use ($user1, $users) { // with custom resolver - $posts = \collect(['author' => $user2], ['author' => $user3], ['author' => $user4]); - $user1->attachFollowStatus($posts, fn ($post) => $post['author']); + $users = \collect(['creator' => $user2], ['creator' => $user3], ['creator' => $user4]); + $user1->attachFollowStatus($users, fn ($post) => $post['creator']); + } + + public function test_order_by_followers() + { + /* @var \Tests\User $user1 */ + /* @var \Tests\User $user2 */ + /* @var \Tests\User $user3 */ + /* @var \Tests\User $user4 */ + /* @var \Tests\User $user5 */ + $user1 = User::create(['name' => 'user1']); + $user2 = User::create(['name' => 'user2']); + $user3 = User::create(['name' => 'user3']); + $user4 = User::create(['name' => 'user4']); + $user5 = User::create(['name' => 'user5']); + + // user2: 2 followers + $user1->follow($user2); + $user3->follow($user2); + + // user3: 0 followers + // user4: 1 followers + $user1->follow($user4); + + // user1: 3 followers + $user2->follow($user1); + $user3->follow($user1); + $user4->follow($user1); + + $usersOrderByFollowersCount = User::orderByFollowersCountDesc()->get(); + // same as: + // $usersOrderByFollowersCount = User::withCount('followers')->orderByDesc('followers_count')->get(); + + $this->assertSame($user1->name, $usersOrderByFollowersCount[0]->name); + $this->assertEquals(3, $usersOrderByFollowersCount[0]->followers_count); + $this->assertSame($user2->name, $usersOrderByFollowersCount[1]->name); + $this->assertEquals(2, $usersOrderByFollowersCount[1]->followers_count); + $this->assertSame($user4->name, $usersOrderByFollowersCount[2]->name); + $this->assertEquals(1, $usersOrderByFollowersCount[2]->followers_count); + $this->assertSame($user3->name, $usersOrderByFollowersCount[3]->name); + $this->assertEquals(0, $usersOrderByFollowersCount[3]->followers_count); + + $mostPopularUser = User::orderByFollowersCountDesc()->first(); + // same as: + // $mostPopularUser = Post::withCount('followers')->orderByDesc('followers_count')->first(); + $this->assertSame($user1->name, $mostPopularUser->name); + $this->assertEquals(3, $mostPopularUser->followers_count); } }