Skip to content

Commit d94860d

Browse files
committed
-
1 parent fb48de3 commit d94860d

File tree

2 files changed

+42
-6
lines changed

2 files changed

+42
-6
lines changed

src/Relations/HasOne.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
use Illuminate\Database\Eloquent\Builder;
88
use Illuminate\Database\Eloquent\Model;
99
use Illuminate\Database\Eloquent\Relations\HasOne as EloquentHasOne;
10+
use Illuminate\Support\Arr;
11+
12+
use function is_null;
1013

1114
class HasOne extends EloquentHasOne
1215
{
@@ -38,6 +41,37 @@ public function getRelationExistenceQuery(Builder $query, Builder $parentQuery,
3841
return $query->select($foreignKey)->where($foreignKey, 'exists', true);
3942
}
4043

44+
protected function newOneOfManySubQuery($groupBy, $columns = null, $aggregate = null)
45+
{
46+
$subQuery = $this->query->getModel()
47+
->newQuery()
48+
->withoutGlobalScopes($this->removedScopes());
49+
50+
foreach (Arr::wrap($groupBy) as $group) {
51+
$subQuery->groupBy($this->qualifyRelatedColumn($group));
52+
}
53+
54+
if (! is_null($columns)) {
55+
foreach ($columns as $key => $column) {
56+
$aggregatedColumn = $subQuery->qualifyColumn($column);
57+
58+
if ($key === 0) {
59+
$aggregatedColumn = ['$' . strtolower($aggregate) => '$' . $aggregatedColumn];
60+
} else {
61+
$aggregatedColumn = ['$min' => '$' . $aggregatedColumn];
62+
}
63+
64+
$subQuery->addSelect([$column . '_aggregate' => $aggregatedColumn]);
65+
}
66+
}
67+
68+
$this->addOneOfManySubQueryConstraints($subQuery, column: null, aggregate: $aggregate);
69+
70+
return $subQuery;
71+
72+
parent::newOneOfManySubQuery($groupBy, $columns, $aggregate);
73+
}
74+
4175
/**
4276
* Get the name of the "where in" method for eager loading.
4377
*

tests/Eloquent/DatabaseEloquentHasOneOfManyTest.php

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ public function testEagerLoadingAppliesConstraintsToInnerJoinSubQuery()
105105
$user = HasOneOfManyTestUser::create();
106106
$relation = $user->latest_login();
107107
$relation->addEagerConstraints([$user]);
108-
$this->assertSame('select MAX("logins"."id") as "id_aggregate", "logins"."user_id" from "logins" where "logins"."user_id" = ? and "logins"."user_id" is not null and "logins"."user_id" in (1) group by "logins"."user_id"', $relation->getOneOfManySubQuery()->toSql());
108+
$this->assertSame('select MAX("logins"."id") as "id_aggregate", "logins"."user_id" from "logins" where "logins"."user_id" = ? and "logins"."user_id" is not null and "logins"."user_id" in (1) group by "logins"."user_id"', $relation->getOneOfManySubQuery()->toMql());
109109
}
110110

111111
public function testGlobalScopeIsNotAppliedWhenRelationIsDefinedWithoutGlobalScope()
@@ -117,7 +117,7 @@ public function testGlobalScopeIsNotAppliedWhenRelationIsDefinedWithoutGlobalSco
117117
$user = HasOneOfManyTestUser::create();
118118
$relation = $user->latest_login_without_global_scope();
119119
$relation->addEagerConstraints([$user]);
120-
$this->assertSame('select "logins".* from "logins" inner join (select MAX("logins"."id") as "id_aggregate", "logins"."user_id" from "logins" where "logins"."user_id" = ? and "logins"."user_id" is not null and "logins"."user_id" in (1) group by "logins"."user_id") as "latestOfMany" on "latestOfMany"."id_aggregate" = "logins"."id" and "latestOfMany"."user_id" = "logins"."user_id" where "logins"."user_id" = ? and "logins"."user_id" is not null', $relation->getQuery()->toSql());
120+
$this->assertSame('select "logins".* from "logins" inner join (select MAX("logins"."id") as "id_aggregate", "logins"."user_id" from "logins" where "logins"."user_id" = ? and "logins"."user_id" is not null and "logins"."user_id" in (1) group by "logins"."user_id") as "latestOfMany" on "latestOfMany"."id_aggregate" = "logins"."id" and "latestOfMany"."user_id" = "logins"."user_id" where "logins"."user_id" = ? and "logins"."user_id" is not null', $relation->getQuery()->toMql());
121121

122122
HasOneOfManyTestLogin::addGlobalScope('test', function ($query) {
123123
});
@@ -131,7 +131,7 @@ public function testGlobalScopeIsNotAppliedWhenRelationIsDefinedWithoutGlobalSco
131131

132132
$user = HasOneOfManyTestUser::create();
133133
$relation = $user->price_without_global_scope();
134-
$this->assertSame('select "prices".* from "prices" inner join (select max("prices"."id") as "id_aggregate", min("prices"."published_at") as "published_at_aggregate", "prices"."user_id" from "prices" inner join (select max("prices"."published_at") as "published_at_aggregate", "prices"."user_id" from "prices" where "published_at" < ? and "prices"."user_id" = ? and "prices"."user_id" is not null group by "prices"."user_id") as "price_without_global_scope" on "price_without_global_scope"."published_at_aggregate" = "prices"."published_at" and "price_without_global_scope"."user_id" = "prices"."user_id" where "published_at" < ? group by "prices"."user_id") as "price_without_global_scope" on "price_without_global_scope"."id_aggregate" = "prices"."id" and "price_without_global_scope"."published_at_aggregate" = "prices"."published_at" and "price_without_global_scope"."user_id" = "prices"."user_id" where "prices"."user_id" = ? and "prices"."user_id" is not null', $relation->getQuery()->toSql());
134+
$this->assertSame('select "prices".* from "prices" inner join (select max("prices"."id") as "id_aggregate", min("prices"."published_at") as "published_at_aggregate", "prices"."user_id" from "prices" inner join (select max("prices"."published_at") as "published_at_aggregate", "prices"."user_id" from "prices" where "published_at" < ? and "prices"."user_id" = ? and "prices"."user_id" is not null group by "prices"."user_id") as "price_without_global_scope" on "price_without_global_scope"."published_at_aggregate" = "prices"."published_at" and "price_without_global_scope"."user_id" = "prices"."user_id" where "published_at" < ? group by "prices"."user_id") as "price_without_global_scope" on "price_without_global_scope"."id_aggregate" = "prices"."id" and "price_without_global_scope"."published_at_aggregate" = "prices"."published_at" and "price_without_global_scope"."user_id" = "prices"."user_id" where "prices"."user_id" = ? and "prices"."user_id" is not null', $relation->getQuery()->toMql());
135135

136136
HasOneOfManyTestPrice::addGlobalScope('test', function ($query) {
137137
});
@@ -145,7 +145,7 @@ public function testQualifyingSubSelectColumn()
145145

146146
public function testItFailsWhenUsingInvalidAggregate()
147147
{
148-
$this->expectException(InvalidArgumentException::class);
148+
$this->expectException(\InvalidArgumentException::class);
149149
$this->expectExceptionMessage('Invalid aggregate [count] used within ofMany relation. Available aggregates: MIN, MAX');
150150
$user = HasOneOfManyTestUser::make();
151151
$user->latest_login_with_invalid_aggregate();
@@ -430,7 +430,8 @@ public function testEagerLoadingWithMultipleAggregates()
430430

431431
public function testWithExists()
432432
{
433-
$user = HasOneOfManyTestUser::create();
433+
self::markTestSkipped('withExists not supported, PHPORM-285');
434+
HasOneOfManyTestUser::create();
434435

435436
$user = HasOneOfManyTestUser::withExists('latest_login')->first();
436437
$this->assertFalse($user->latest_login_exists);
@@ -442,7 +443,8 @@ public function testWithExists()
442443

443444
public function testWithExistsWithConstraintsInJoinSubSelect()
444445
{
445-
$user = HasOneOfManyTestUser::create();
446+
self::markTestSkipped('withExists not supported, PHPORM-285');
447+
HasOneOfManyTestUser::create();
446448

447449
$user = HasOneOfManyTestUser::withExists('foo_state')->first();
448450

0 commit comments

Comments
 (0)