Skip to content

Commit 44d48d7

Browse files
committed
added method withMax
1 parent 3b96705 commit 44d48d7

File tree

4 files changed

+217
-1
lines changed

4 files changed

+217
-1
lines changed

src/Collection/LaravelSubQueryCollection.php

+32
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,36 @@ public function loadMin($relations)
7070

7171
return $this;
7272
}
73+
74+
/**
75+
* Load a set of relationship min of column onto the collection.
76+
*
77+
* @param array|string $relations
78+
* @return $this
79+
*/
80+
public function loadMax($relations)
81+
{
82+
if ($this->isEmpty()) {
83+
return $this;
84+
}
85+
86+
$models = $this->first()->newModelQuery()
87+
->whereKey($this->modelKeys())
88+
->select($this->first()->getKeyName())
89+
->withMax(...func_get_args())
90+
->get();
91+
92+
$attributes = Arr::except(
93+
array_keys($models->first()->getAttributes()),
94+
$models->first()->getKeyName()
95+
);
96+
97+
$models->each(function ($model) use ($attributes) {
98+
$this->find($model->getKey())->forceFill(
99+
Arr::only($model->getAttributes(), $attributes)
100+
)->syncOriginalAttributes($attributes);
101+
});
102+
103+
return $this;
104+
}
73105
}

src/LaravelSubQuery.php

+18-1
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,19 @@ class LaravelSubQuery extends Builder
1818
protected $withSum = [];
1919

2020
/**
21-
* The relationship sums that should be eager loaded on every query.
21+
* The relationship min value that should be eager loaded on every query.
2222
*
2323
* @var array
2424
*/
2525
protected $withMin = [];
2626

27+
/**
28+
* The relationship max value that should be eager loaded on every query.
29+
*
30+
* @var array
31+
*/
32+
protected $withMax = [];
33+
2734
public function withSum($relations)
2835
{
2936
return $this->withSubQuery($relations, 'sum');
@@ -34,6 +41,11 @@ public function withMin($relations)
3441
return $this->withSubQuery($relations, 'min');
3542
}
3643

44+
public function withMax($relations)
45+
{
46+
return $this->withSubQuery($relations, 'max');
47+
}
48+
3749
protected function withSubQuery($relations, $type)
3850
{
3951
if (empty($relations)) {
@@ -123,4 +135,9 @@ public function setWithMin($withMin)
123135
{
124136
return $this->withMin($withMin);
125137
}
138+
139+
public function setWithMax($withMax)
140+
{
141+
return $this->withMax($withMax);
142+
}
126143
}

src/Traits/LaravelSubQueryTrait.php

+19
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,21 @@ public function loadMin($relations)
3939
return $this;
4040
}
4141

42+
/**
43+
* Eager load relation max value on the model.
44+
*
45+
* @param array|string $relations
46+
* @return $this
47+
*/
48+
public function loadMax($relations)
49+
{
50+
$relations = is_string($relations) ? func_get_args() : $relations;
51+
52+
$this->newCollection([$this])->loadMax($relations);
53+
54+
return $this;
55+
}
56+
4257
public function newEloquentBuilder($builder)
4358
{
4459
$newEloquentBuilder = new LaravelSubQuery($builder);
@@ -52,6 +67,10 @@ public function newEloquentBuilder($builder)
5267
$newEloquentBuilder->setWithMin($this->withMin);
5368
}
5469

70+
if (isset($this->withMax)) {
71+
$newEloquentBuilder->setWithMax($this->withMax);
72+
}
73+
5574
return $newEloquentBuilder;
5675
}
5776

tests/LaravelSubQueryWithMaxTest.php

+148
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
<?php
2+
3+
namespace Alexmg86\LaravelSubQuery\Tests;
4+
5+
use Alexmg86\LaravelSubQuery\Facades\LaravelSubQuery;
6+
use Alexmg86\LaravelSubQuery\ServiceProvider;
7+
use Illuminate\Database\Eloquent\Builder;
8+
use Illuminate\Database\Schema\Blueprint;
9+
use Illuminate\Support\Facades\Schema;
10+
11+
class LaravelSubQueryWithMaxTest extends DatabaseTestCase
12+
{
13+
protected function getPackageProviders($app)
14+
{
15+
return [ServiceProvider::class];
16+
}
17+
18+
protected function getPackageAliases($app)
19+
{
20+
return [
21+
'laravel-sub-query' => LaravelSubQuery::class,
22+
];
23+
}
24+
25+
protected function setUp(): void
26+
{
27+
parent::setUp();
28+
29+
Schema::create('invoices', function (Blueprint $table) {
30+
$table->increments('id');
31+
$table->string('name', 100);
32+
});
33+
34+
Schema::create('items', function (Blueprint $table) {
35+
$table->increments('id');
36+
$table->integer('invoice_id');
37+
$table->integer('price');
38+
$table->integer('price2');
39+
});
40+
41+
Schema::create('goods', function (Blueprint $table) {
42+
$table->increments('id');
43+
$table->integer('invoice_id');
44+
$table->integer('price');
45+
$table->integer('price2');
46+
});
47+
}
48+
49+
public function testBasic()
50+
{
51+
$invoice = Invoice::create(['id' => 1, 'name' => 'text_name']);
52+
for ($i = 1; $i < 11; $i++) {
53+
Item::create(['invoice_id' => $invoice->id, 'price' => $i, 'price2' => $i + 1]);
54+
Good::create(['invoice_id' => $invoice->id, 'price' => $i, 'price2' => $i + 1]);
55+
}
56+
57+
$results = Invoice::withMax('items:price,price2');
58+
59+
$this->assertEquals([
60+
['id' => 1, 'name' => 'text_name', 'items_price_max' => 10, 'items_price2_max' => 11],
61+
], $results->get()->toArray());
62+
}
63+
64+
public function testWithConditions()
65+
{
66+
$invoice = Invoice::create(['id' => 1, 'name' => 'text_name']);
67+
for ($i = 1; $i < 11; $i++) {
68+
Item::create(['invoice_id' => $invoice->id, 'price' => $i, 'price2' => $i + 1]);
69+
Good::create(['invoice_id' => $invoice->id, 'price' => $i, 'price2' => $i + 1]);
70+
}
71+
72+
$results = Invoice::withMax(['items:price', 'goods:price,price2' => function (Builder $query) {
73+
$query->where('price', '>', 6);
74+
}]);
75+
76+
$this->assertEquals([
77+
['id' => 1, 'name' => 'text_name', 'items_price_max' => 10, 'goods_price_max' => 10, 'goods_price2_max' => 11],
78+
], $results->get()->toArray());
79+
}
80+
81+
public function testWithSelect()
82+
{
83+
$invoice = Invoice::create(['id' => 1, 'name' => 'text_name']);
84+
for ($i = 1; $i < 11; $i++) {
85+
Item::create(['invoice_id' => $invoice->id, 'price' => $i, 'price2' => $i + 1]);
86+
}
87+
88+
$results = Invoice::select(['id'])->withMax('items:price');
89+
90+
$this->assertEquals([
91+
['id' => 1, 'items_price_max' => 10],
92+
], $results->get()->toArray());
93+
}
94+
95+
public function testLoadMax()
96+
{
97+
$invoice = Invoice::create(['id' => 1, 'name' => 'text_name']);
98+
for ($i = 1; $i < 11; $i++) {
99+
Item::create(['invoice_id' => $invoice->id, 'price' => $i, 'price2' => $i + 1]);
100+
}
101+
102+
$results = Invoice::first();
103+
$results->loadMax('items:price');
104+
105+
$this->assertEquals(['id' => 1, 'name' => 'text_name', 'items_price_max' => 10], $results->toArray());
106+
}
107+
108+
public function testLoadMaxWithConditions()
109+
{
110+
$invoice = Invoice::create(['id' => 1, 'name' => 'text_name']);
111+
for ($i = 1; $i < 11; $i++) {
112+
Item::create(['invoice_id' => $invoice->id, 'price' => $i, 'price2' => $i + 1]);
113+
}
114+
115+
$results = Invoice::first();
116+
$results->loadMax(['items:price' => function ($query) {
117+
$query->where('price', '>', 5);
118+
}]);
119+
120+
$this->assertEquals(['id' => 1, 'name' => 'text_name', 'items_price_max' => 10], $results->toArray());
121+
}
122+
123+
public function testGlobalScopes()
124+
{
125+
$invoice = Invoice::create(['id' => 1, 'name' => 'text_name']);
126+
for ($i = 1; $i < 11; $i++) {
127+
Good::create(['invoice_id' => $invoice->id, 'price' => $i, 'price2' => $i + 1]);
128+
}
129+
130+
$result = Invoice::withMax('goods:price')->first();
131+
$this->assertEquals(10, $result->goods_price_max);
132+
133+
$result = Invoice::withMax('allGoods:price')->first();
134+
$this->assertEquals(10, $result->all_goods_price_max);
135+
}
136+
137+
public function testSortingScopes()
138+
{
139+
$invoice = Invoice::create(['id' => 1, 'name' => 'text_name']);
140+
for ($i = 1; $i < 11; $i++) {
141+
Item::create(['invoice_id' => $invoice->id, 'price' => $i, 'price2' => $i + 1]);
142+
}
143+
144+
$result = Invoice::withMax('items:price')->toSql();
145+
146+
$this->assertSame('select "invoices".*, (select max(price) from "items" where "invoices"."id" = "items"."invoice_id") as "items_price_max" from "invoices"', $result);
147+
}
148+
}

0 commit comments

Comments
 (0)