Przypomnienie w zasadzie wszystkich relacji, jakie przerabialiśmy plus poznanie polimorficznego one of many. Do dzieła.
Rzućmy okiem na model movie i zastanówmy się, jakie ma relacje:
class Movie extends Model
{
use HasFactory;
protected $fillable = ["title", "director", "length", "release_date"];
public function reviews(){
return $this->hasMany(Review::class);
}
public function latestReview()
{
return $this->hasOne(Review::class)->latestOfMany();
}
public function oldestReview()
{
return $this->hasOne(Review::class)->oldestOfMany();
}
public function worstReview()
{
return $this->hasOne(Review::class)->ofMany('rating', 'min');
}
public function bestReview()
{
return $this->hasOne(Review::class)->ofMany('rating', 'max');
}
public function image()
{
return $this->morphOne(Image::class, 'imageable');
}
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
}
Relacje movie:
- reviews, hasMany, czyli zwykłe one to many, gdzie Movie jest rodzicem a Review dzieckem (belongsTo Movie)
- latestReview i oldestReview, czyli has one of many
- worstReview i bestReview, czyli has one of many z nazwą tabeli w relacji i funkcją sortującą
- image, morphOne, czyli polimorficzne hasOne, gdzie image ma imageable morphTo (puste)
- comments, czyli morphMany, polimorficzne hasMany, gdzie comment ma commentable morphTo (puste)
Ogarnijmy te relacje, od obu stron, potem jeszcze od stron tabel w bazie danych i jedziemy z polimorficznym has one of many (w review):
class Review extends Model
{
use HasFactory;
protected $fillable = ["author", "content", "rating"];
public function movie(){
return $this->belongsTo(Movie::class);
}
public function tags(){
return $this->belongsToMany(Tag::class)->withTimestamps();
}
public function image()
{
return $this->morphOne(Image::class, 'imageable');
}
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
public function latestComment()
{
return $this->morphOne(Comment::class, 'commentable')->latestOfMany();
}
public function oldestComment()
{
return $this->morphOne(Comment::class, 'commentable')->oldestOfMany();
}
}
Mamy tutaj:
- movie, czyli belongsTo, odwrotna strona relacji one 2 one (hasOne)
- tags, czyli belongsToMany, czyli relacja manyToMany, Tag również ma belongsToMany z klasą Review
- image, morphOne, czyli poliumorficzne hasOne
- comments, morphMany, polimorficzne hasMany
- latestComment i oldestComment, dodaliśmy dopiero teraz, polimorficzne wersje has one of many.
To wszystko musi się w głowie ułożyć. Wykonajmy kilka ćwiczeń:
Artisan::command('r-latest-comment {id}', function (int $id) {
$r = Review::with('latestComment')->findOrFail($id);
$this->comment("Review author: {$r->author}");
$this->comment("Movie id: {$r->movie_id}");
$this->comment("Latest comment title: {$r->latestComment->title}");
$this->comment("Latest comment created_at: {$r->latestComment->created_at}");
});
Teraz druga z naszych relacji:
Artisan::command('r-oldest-comment {id}', function (int $id) {
$r = Review::with('oldestComment')->findOrFail($id);
$this->comment("Review author: {$r->author}");
$this->comment("Movie id: {$r->movie_id}");
$this->comment("Oldest comment title: {$r->oldestComment->title}");
$this->comment("Oldest comment created_at: {$r->oldestComment->created_at}");
});
Pobawmy się tym, jeszcze raz przeanalizujmy wszystko, aby upewnić się, że rozumiemy.