Poznajemy relację has one of many na podstawie Movie i Review będących w relacji hasMany/belongsTo. Do dzieła.
Ok, nasz model:
class Movie extends Model
{
use HasFactory;
protected $fillable = ["title", "director", "length", "release_date"];
public function reviews(){
return $this->hasMany(Review::class);
}
}
Dodajemy hasOne (of Many), ostatnia recenzja i najstarsza:
public function latestReview()
{
return $this->hasOne(Review::class)->latestOfMany();
}
public function oldestReview()
{
return $this->hasOne(Review::class)->oldestOfMany();
}
Proste. A inne sztuczki? Cóż, najpierw ->hasOne, potem ->ofMany, nazwa kolumny i nazwa funkcji agregującej, którą użyjemy do sortowania:
public function worstReview()
{
return $this->hasOne(Review::class)->ofMany('rating', 'min');
}
public function bestReview()
{
return $this->hasOne(Review::class)->ofMany('rating', 'max');
}
Czyli tak, hasOne do modelu, na którym mamy hasMany, ofMany, rating – nazwa kolumny, min – daj najgorszy. Max – najlepszy.
To teraz nasze komendy. Pierwsza:
Artisan::command('m-latest-review {id}', function (int $id) {
$m = Movie::with('latestReview')->findOrFail($id);
$this->comment("Title: {$m->title}");
$this->comment("Latest review: {$m->latestReview->created_at}");
$this->comment("Author: {$m->latestReview->author}");
$this->comment("Content: {$m->latestReview->content}");
$this->comment("Rating: {$m->latestReview->rating}");
});
Druga podobnie:
Artisan::command('m-oldest-review {id}', function (int $id) {
$m = Movie::with('oldestReview')->findOrFail($id);
$this->comment("Title: {$m->title}");
$this->comment("Oldest review: {$m->oldestReview->created_at}");
$this->comment("Author: {$m->oldestReview->author}");
$this->comment("Content: {$m->oldestReview->content}");
$this->comment("Rating: {$m->oldestReview->rating}");
});
Trzecia, żadnej filozofii nie ma:
Artisan::command('m-best-review {id}', function (int $id) {
$m = Movie::with('bestReview')->findOrFail($id);
$this->comment("Title: {$m->title}");
$this->comment("Best review: {$m->bestReview->created_at}");
$this->comment("Author: {$m->bestReview->author}");
$this->comment("Content: {$m->bestReview->content}");
$this->comment("Rating: {$m->bestReview->rating}");
});
I czwarta:
Artisan::command('m-worst-review {id}', function (int $id) {
$m = Movie::with('worstReview')->findOrFail($id);
$this->comment("Title: {$m->title}");
$this->comment("Worst review: {$m->worstReview->created_at}");
$this->comment("Author: {$m->worstReview->author}");
$this->comment("Content: {$m->worstReview->content}");
$this->comment("Rating: {$m->worstReview->rating}");
});
To akurat nie było nic trudnego, aczkolwiek po to uczymy się SQL i po to dogłębnie zgłębiamy temat, aby nic nas nie zaskakiwało, tak samo znamy concat (w SQL) jak i atrybuty (w modelu), tak samo znamy funkcje agregujące jak i relacje Eloquenta.
Nie ma drogi na skróty, niestety, dużo jest tej nauki, ale warto!