Skip to content

Commit f42ae50

Browse files
akr4mtaylorotwell
andauthored
[10.x] Add whenAggregated method to ConditionallyLoadsAttributes trait (#47417)
* Added `whenAveraged` * Update ConditionallyLoadsAttributes.php * Added whenAggregated * Added tests --------- Co-authored-by: Taylor Otwell <[email protected]>
1 parent 33afb59 commit f42ae50

File tree

3 files changed

+106
-0
lines changed

3 files changed

+106
-0
lines changed

src/Illuminate/Http/Resources/ConditionallyLoadsAttributes.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,35 @@ public function whenCounted($relationship, $value = null, $default = null)
300300
return value($value, $this->resource->{$attribute});
301301
}
302302

303+
/**
304+
* Retrieve a relationship aggregated value if it exists.
305+
*
306+
* @param string $relationship
307+
* @param string $column
308+
* @param string $aggregate
309+
* @param mixed $value
310+
* @param mixed $default
311+
* @return \Illuminate\Http\Resources\MissingValue|mixed
312+
*/
313+
public function whenAggregated($relationship, $column, $aggregate, $value = null, $default = null)
314+
{
315+
$attribute = (string) Str::of($relationship)->snake()->append('_')->append($aggregate)->append('_')->finish($column);
316+
317+
if (! isset($this->resource->getAttributes()[$attribute])) {
318+
return value($default);
319+
}
320+
321+
if (func_num_args() === 3) {
322+
return $this->resource->{$attribute};
323+
}
324+
325+
if ($this->resource->{$attribute} === null) {
326+
return;
327+
}
328+
329+
return value($value, $this->resource->{$attribute});
330+
}
331+
303332
/**
304333
* Execute a callback if the given pivot table has been loaded.
305334
*
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace Illuminate\Tests\Integration\Http\Fixtures;
4+
5+
class PostResourceWithOptionalRelationshipAggregates extends PostResource
6+
{
7+
public function toArray($request)
8+
{
9+
return [
10+
'id' => $this->id,
11+
'title' => $this->title,
12+
'average_rating' => $this->whenAggregated('comments', 'rating', 'avg'),
13+
'minimum_rating' => $this->whenAggregated('comments', 'rating', 'min'),
14+
'maximum_rating' => $this->whenAggregated('comments', 'rating', 'max', fn ($avg) => "$avg ratings", 'Default Value'),
15+
];
16+
}
17+
}

tests/Integration/Http/ResourceTest.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithOptionalMerging;
3636
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithOptionalPivotRelationship;
3737
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithOptionalRelationship;
38+
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithOptionalRelationshipAggregates;
3839
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithOptionalRelationshipCounts;
3940
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithoutWrap;
4041
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithUnlessOptionalData;
@@ -449,6 +450,65 @@ public function testResourcesMayLoadOptionalRelationships()
449450
]);
450451
}
451452

453+
public function testResourcesMayLoadOptionalRelationshipAggregates()
454+
{
455+
Route::get('/', function () {
456+
$post = new Post([
457+
'id' => 5,
458+
'title' => 'Test Title',
459+
'comments_avg_rating' => 3.8,
460+
'comments_min_rating' => 2,
461+
'comments_max_rating' => 5
462+
]);
463+
464+
return new PostResourceWithOptionalRelationshipAggregates($post);
465+
});
466+
467+
$response = $this->withoutExceptionHandling()->get(
468+
'/', ['Accept' => 'application/json']
469+
);
470+
471+
$response->assertStatus(200);
472+
473+
$response->assertExactJson([
474+
'data' => [
475+
'id' => 5,
476+
'title' => 'Test Title',
477+
'average_rating' => 3.8,
478+
'minimum_rating' => 2,
479+
'maximum_rating' => "5 ratings",
480+
],
481+
]);
482+
}
483+
484+
public function testResourcesMayHaveOptionalRelationshipAggregates()
485+
{
486+
Route::get('/', function () {
487+
$post = new Post([
488+
'id' => 5,
489+
'title' => 'Test Title',
490+
]);
491+
492+
return new PostResourceWithOptionalRelationshipAggregates($post);
493+
});
494+
495+
$response = $this->withoutExceptionHandling()->get(
496+
'/', ['Accept' => 'application/json']
497+
);
498+
499+
$response->assertStatus(200);
500+
501+
$response->assertExactJson([
502+
'data' => [
503+
'id' => 5,
504+
'title' => 'Test Title',
505+
'average_rating' => null,
506+
'minimum_rating' => null,
507+
'maximum_rating' => "Default Value",
508+
],
509+
]);
510+
}
511+
452512
public function testResourcesMayShowsNullForLoadedRelationshipWithValueNull()
453513
{
454514
Route::get('/', function () {

0 commit comments

Comments
 (0)