Skip to content

Commit b16665b

Browse files
authored
Merge pull request #3 from nullthoughts/dev
Support for earliest-relation
2 parents e29d8cc + cd768f9 commit b16665b

File tree

3 files changed

+80
-24
lines changed

3 files changed

+80
-24
lines changed

README.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ Install via composer:
88
## Usage / Examples
99
Use the Builder methods inside a whereHas closure:
1010

11-
### whereLatest($column, $value)
11+
### Latest:
12+
13+
#### whereLatest($column, $value)
1214
**Query**
1315
```php
1416
$users = User::whereHas('logins', function ($query) {
@@ -26,7 +28,7 @@ public function scopeByCondition($query, $condition)
2628
}
2729
```
2830

29-
### latestRelation()
31+
#### latestRelation()
3032
**Query**
3133
```php
3234
$users = User::whereHas('logins', function ($query) {
@@ -47,3 +49,15 @@ public function scopeByCondition($query, $condition)
4749
});
4850
}
4951
```
52+
53+
### Earliest:
54+
55+
```php
56+
$users = User::whereHas('logins', function ($query) {
57+
$query->whereEarliest('device_type', 'desktop');
58+
});
59+
60+
$users = User::whereHas('logins', function ($query) {
61+
$query->earliestRelation()->whereNotNull('device_type');
62+
});
63+
```

src/ServiceProvider.php

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,29 @@ class ServiceProvider extends BaseServiceProvider
1010
{
1111
public function boot()
1212
{
13-
Builder::macro('latestRelation', function () {
13+
Builder::macro('relation', function (string $type = 'max') {
1414
if(! $where = $this->wheres[0] ?? null) {
15-
throw new InvalidArgumentException('The latestRelation method should only be called from within a whereHas callback.');
15+
throw new InvalidArgumentException('The relation methods should only be called from within a whereHas callback.');
1616
}
1717

18-
return $this->where('id', function ($sub) use ($where) {
18+
return $this->where('id', function ($sub) use ($where, $type) {
1919
$sub->from($this->from)
20-
->selectRaw('max(id)')
21-
->whereColumn($where['first'], $where['second']);
20+
->selectRaw($type . '(id)')
21+
->whereColumn($where['first'], $where['second']);
2222
});
2323
});
24+
25+
Builder::macro('earliestRelation', function () {
26+
return $this->relation('min');
27+
});
28+
29+
Builder::macro('latestRelation', function () {
30+
return $this->relation('max');
31+
});
32+
33+
Builder::macro('whereEarliest', function ($column, $value) {
34+
return $this->earliestRelation()->where($column, $value);
35+
});
2436

2537
Builder::macro('whereLatest', function ($column, $value) {
2638
return $this->latestRelation()->where($column, $value);

tests/Unit/EloquentLatestRelationTest.php

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public function setUp(): void
2727
$table->timestamp('created_at');
2828
$table->unsignedBigInteger('user_id');
2929
$table->enum('device_type', ['mobile', 'desktop']);
30-
$table->string('profession')->nullable();
30+
$table->string('country')->nullable();
3131
});
3232

3333
DB::table('users')->insert([
@@ -48,49 +48,48 @@ public function setUp(): void
4848
'user_id' => 1,
4949
'created_at' => Carbon::now()->subDays(3),
5050
'device_type' => 'mobile',
51-
'profession' => null
51+
'country' => null
5252
], [
5353

5454
'user_id' => 2,
5555
'created_at' => Carbon::now()->subDays(3),
5656
'device_type' => 'mobile',
57-
'profession' => null
57+
'country' => null
5858
], [
5959
'user_id' => 3,
6060
'created_at' => Carbon::now()->subDays(3),
6161
'device_type' => 'mobile',
62-
'profession' => null],
63-
64-
[
62+
'country' => 'US'
63+
], [
6564
'user_id' => 1,
6665
'created_at' => Carbon::now()->subDay(2),
6766
'device_type' => 'desktop',
68-
'profession' => null
67+
'country' => null
6968
], [
7069
'user_id' => 2,
7170
'created_at' => Carbon::now()->subDay(2),
7271
'device_type' => 'desktop',
73-
'profession' => null
72+
'country' => null
7473
], [
7574
'user_id' => 3,
7675
'created_at' => Carbon::now()->subDay(2),
7776
'device_type' => 'desktop',
78-
'profession' => null
77+
'country' => null
7978
], [
8079
'user_id' => 1,
8180
'created_at' => Carbon::now(),
8281
'device_type' => 'desktop',
83-
'profession' => 'Leisure Consultant'
82+
'country' => 'US'
8483
], [
8584
'user_id' => 2,
8685
'created_at' => Carbon::now()->subDay(1),
8786
'device_type' => 'mobile',
88-
'profession' => null
87+
'country' => null
8988
], [
9089
'user_id' => 3,
9190
'created_at' => Carbon::now(),
9291
'device_type' => 'mobile',
93-
'profession' => null
92+
'country' => null
9493
],
9594
]);
9695
}
@@ -100,12 +99,12 @@ public function setUp(): void
10099
*/
101100
public function latest_relation()
102101
{
103-
$professions = User::whereHas('logins', function ($query) {
104-
$query->latestRelation()->whereNotNull('profession');
102+
$users = User::whereHas('logins', function ($query) {
103+
$query->latestRelation()->whereNotNull('country');
105104
});
106105

107-
$this->assertSame(1, $professions->count());
108-
$this->assertSame('Ferris Bueller', $professions->first()->name);
106+
$this->assertSame(1, $users->count());
107+
$this->assertSame('Ferris Bueller', $users->first()->name);
109108

110109
$loggedInYesterday = User::whereHas('logins', function ($query) {
111110
$query->latestRelation()->whereBetween(
@@ -118,7 +117,20 @@ public function latest_relation()
118117
$this->assertSame(1, $loggedInYesterday->count());
119118
$this->assertSame('Cameron Frye', $loggedInYesterday->first()->name);
120119
}
121-
120+
121+
/**
122+
* @test
123+
*/
124+
public function earilest_relation()
125+
{
126+
$users = User::whereHas('logins', function ($query) {
127+
$query->earliestRelation()->whereNotNull('country');
128+
});
129+
130+
$this->assertSame(1, $users->count());
131+
$this->assertSame('Ed Rooney', $users->first()->name);
132+
}
133+
122134
/**
123135
* @test
124136
*/
@@ -144,6 +156,24 @@ public function where_latest()
144156
$this->assertSame('Ferris Bueller', $users->first()->name);
145157
$this->assertSame('desktop', $users->first()->lastLogin->device_type);
146158
}
159+
160+
/**
161+
* @test
162+
*/
163+
public function where_earilest()
164+
{
165+
$users = User::whereHas('logins', function ($query) {
166+
$query->whereEarliest('device_type', 'mobile');
167+
})->get();
168+
169+
$this->assertCount(3, $users);
170+
171+
$users = User::whereHas('logins', function ($query) {
172+
$query->whereEarliest('device_type', 'desktop');
173+
})->get();
174+
175+
$this->assertCount(0, $users);
176+
}
147177
}
148178

149179
class User extends Model

0 commit comments

Comments
 (0)