Skip to content

Commit 9971d5d

Browse files
committed
Add HasManyThrough example
Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>
1 parent 4c66617 commit 9971d5d

File tree

10 files changed

+166
-11
lines changed

10 files changed

+166
-11
lines changed

app/Http/Resources/PostResource.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@
66

77
class PostResource extends JsonApiResource
88
{
9+
/**
10+
* The resource's relationships.
11+
*
12+
* @var list<string>
13+
*/
14+
protected array $relationships = [
15+
'comments',
16+
'user',
17+
];
18+
919
/**
1020
* The resource's attributes.
1121
*

app/Http/Resources/UserResource.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ class UserResource extends JsonApiResource
1313
public function toRelationships(Request $request)
1414
{
1515
return [
16+
'comments',
1617
'posts',
1718
'profile',
19+
'reactions',
1820
'teams',
1921
];
2022
}

app/Models/Comment.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
namespace App\Models;
4+
5+
use Illuminate\Database\Eloquent\Factories\HasFactory;
6+
use Illuminate\Database\Eloquent\Model;
7+
use Illuminate\Database\Eloquent\Relations\BelongsTo;
8+
9+
class Comment extends Model
10+
{
11+
/** @use HasFactory<\Database\Factories\CommentFactory> */
12+
use HasFactory;
13+
14+
/**
15+
* Get the post that owns the comment.
16+
*/
17+
public function post(): BelongsTo
18+
{
19+
return $this->belongsTo(Post::class);
20+
}
21+
22+
/**
23+
* Get the user that owns the comment.
24+
*/
25+
public function user(): BelongsTo
26+
{
27+
return $this->belongsTo(User::class);
28+
}
29+
}

app/Models/Post.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,27 @@
44

55
use Illuminate\Database\Eloquent\Factories\HasFactory;
66
use Illuminate\Database\Eloquent\Model;
7+
use Illuminate\Database\Eloquent\Relations\BelongsTo;
8+
use Illuminate\Database\Eloquent\Relations\HasMany;
79

810
class Post extends Model
911
{
1012
/** @use HasFactory<\Database\Factories\PostFactory> */
1113
use HasFactory;
14+
15+
/**
16+
* Get the comments for the post.
17+
*/
18+
public function comments(): HasMany
19+
{
20+
return $this->hasMany(Comment::class);
21+
}
22+
23+
/**
24+
* Get the user that owns the post.
25+
*/
26+
public function user(): BelongsTo
27+
{
28+
return $this->belongsTo(User::class);
29+
}
1230
}

app/Models/User.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
use Illuminate\Database\Eloquent\Factories\HasFactory;
66
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
7+
use Illuminate\Database\Eloquent\Relations\HasMany;
8+
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
79
use Illuminate\Database\Eloquent\Relations\HasOne;
810
use Illuminate\Foundation\Auth\User as Authenticatable;
911
use Illuminate\Notifications\Notifiable;
@@ -72,4 +74,28 @@ public function teams(): BelongsToMany
7274
->using(Membership::class)
7375
->as('membership');
7476
}
77+
78+
/**
79+
* Get the posts for the user.
80+
*/
81+
public function posts(): HasMany
82+
{
83+
return $this->hasMany(Post::class);
84+
}
85+
86+
/**
87+
* Get the comments for the user.
88+
*/
89+
public function comments(): HasMany
90+
{
91+
return $this->hasMany(Comment::class);
92+
}
93+
94+
/**
95+
* Get all of the reactions for the user.
96+
*/
97+
public function reactions(): HasManyThrough
98+
{
99+
return $this->hasManyThrough(Comment::class, Post::class);
100+
}
75101
}

composer.lock

Lines changed: 10 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
namespace Database\Factories;
4+
5+
use App\Models\Post;
6+
use Illuminate\Database\Eloquent\Factories\Factory;
7+
8+
/**
9+
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Comment>
10+
*/
11+
class CommentFactory extends Factory
12+
{
13+
/**
14+
* Define the model's default state.
15+
*
16+
* @return array<string, mixed>
17+
*/
18+
public function definition(): array
19+
{
20+
return [
21+
'post_id' => PostFactory::new(),
22+
'user_id' => UserFactory::new(),
23+
'content' => $this->faker->words(10, true),
24+
];
25+
}
26+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*/
12+
public function up(): void
13+
{
14+
Schema::create('comments', function (Blueprint $table) {
15+
$table->id();
16+
$table->foreignId('post_id')->unique();
17+
$table->foreignId('user_id')->index()->nullable();
18+
$table->text('content');
19+
$table->timestamps();
20+
});
21+
}
22+
23+
/**
24+
* Reverse the migrations.
25+
*/
26+
public function down(): void
27+
{
28+
Schema::dropIfExists('comments');
29+
}
30+
};

database/seeders/DatabaseSeeder.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Database\Seeders;
44

55
use App\Enums\TeamRole;
6+
use App\Models\Comment;
67
use App\Models\Post;
78
use App\Models\Team;
89
use App\Models\User;
@@ -35,6 +36,15 @@ public function run(): void
3536
$user->teams()->attach($team, ['role' => TeamRole::MEMBER]);
3637

3738
User::factory(10)->create();
38-
Post::factory(50)->create();
39+
$posts = Post::factory(50)->create();
40+
41+
tap($posts->first(), function (Post $post) use ($user) {
42+
$post->user_id = $user->getKey();
43+
})->save();
44+
45+
Comment::factory()->create([
46+
'post_id' => $posts->first()->getKey(),
47+
'user_id' => $user->getKey(),
48+
]);
3949
}
4050
}

routes/api.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66
use App\Models\UserProfile;
77
use Illuminate\Support\Facades\Route;
88

9-
Route::get('users', fn () => User::paginate(10)->toResourceCollection());
9+
Route::get('users', fn () => User::paginate(50)->toResourceCollection());
1010
Route::get('users/{user}', fn (User $user) => $user->toResource());
1111

12-
Route::get('user-profiles', fn () => UserProfile::paginate(10)->toResourceCollection());
12+
Route::get('user-profiles', fn () => UserProfile::paginate(50)->toResourceCollection());
1313
Route::get('user-profiles/{userProfile}', fn (UserProfile $userProfile) => $userProfile->toResource());
1414

15-
Route::get('posts', fn () => Post::paginate(10)->toResourceCollection());
15+
Route::get('posts', fn () => Post::paginate(50)->toResourceCollection());
1616
Route::get('posts/{post}', fn (Post $post) => $post->toResource());
1717

18-
Route::get('teams', fn () => Team::paginate(10)->toResourceCollection());
18+
Route::get('teams', fn () => Team::paginate(50)->toResourceCollection());
1919
Route::get('teams/{team}', fn (Team $team) => $team->toResource());

0 commit comments

Comments
 (0)