laravelフレームワークを使用するためにデータベーススキーマを定義しようとしています。サッカーの試合をモデル化したいと思います。最初に実行したいステップは、エンティティ関係図を定義することですが、これ(私は非常に些細なことだと思いました)は、いくつかの面で混乱を招きます。
まず、明らかなアプローチは、試合は2つのチームに関連しており、チームは任意の数の試合に関連していると言うことです。したがって、「多対多」の関係になります。
しかし、多対多の関係の実装は、両方のエンティティを関連付けるために2つのテーブルと中間テーブルを持つことです。マッチには常に2つのチームがあり、Teamsテーブルへの外部キーを持つ2つの列(local_idとvisitant_id)があるだけで十分であることがわかっている場合、これは多すぎると思います。さらに、私はできることをしたい:
Match::find(1)->local() or Match::find(1)->visitant();
それで、これを考えて、私は「1対多」の関係を実装していますが、これには別の問題があります。チームがプレイしたすべての試合を取得するには、次のようにします。
Team::find(1)->matches();
しかし、eloquentでmatches()メソッドを定義するときに指定できるキー列は1つだけなので、これを行うことはできません(デフォルトでは、team_idになりますが、visitant_idとlocal_idである必要があります)。
ソースコードをさらに掘り下げた後、データベーススキーマを実際にそのままにして、目的を達成する方法があることがわかりました(少なくともLaravel 4)で)問題を投稿しましたgithubとTaylorOtwell(フレームワークの作成者)は私に正しい答えをくれました: https://github.com/laravel/framework/issues/1272
彼を引用すると、それはこれと同じくらい簡単なはずです:
class Team extends Eloquent {
public function allMatches()
{
return $this->hasMany('Match', 'visitant_id')->orWhere('local_id', $this->id);
}
}
その後...
$team = Team::find(2);
$matches = $team->allMatches;
更新:laravelはバグレポートをそのように受け取らないため、githubリンクは機能していません:- http://laravel-news.com/2014/09/laravel-removes-github-issues/
これは、それらの有名なデータベース設計の問題の1つです。たとえば、友情関係は同じ困難に苦しんでいます。 Eloquentを使用しているので、多対多のアプローチに固執し、中間テーブルに追加のブール列local
を設定することをお勧めします。
_class Match extends Eloquent {
public $includes = array('team'); // Always eager load teams
public function teams() {
return $this->has_many_and_belongs_to('team')->with('local');
}
public function get_local() {
foreach ($this->teams as $team) {
if ($team->pivot->local) return $team;
}
}
public function get_visitant() {
foreach ($this->teams as $team) {
if (!$team->pivot->local) return $team;
}
}
}
class Team extends Eloquent {
public function matches() {
return $this->has_many_and_belongs_to('match')->with('local');
}
// I'm doing separate queries here because a team may have
// hundreds of matches and it's not worth looping through
// all of them to retrieve the local ones
public function matches_as_local() {
return $this->has_many_and_belongs_to('match')->with('local')
->where('pivot_local', '=', 1);
}
public function matches_as_visitant() {
return $this->has_many_and_belongs_to('match')->with('local')
->where('pivot_local', '=', 0);
}
}
_
Obs:
メソッドhas_many_and_belongs_to(...)->with('field')
は、積極的な読み込みとは何の関係もありません。 Eloquentに中間テーブル列field
をロードし、それをピボットに配置するように指示します。
使用法:
_$match = Match::find(1);
$match->local; // returns local team
$match->visitant; // returns visitant team
$team = Team::find(1);
$team->matches; // returns all matches
$team->matches_as_local; // ...
$team->matches_as_visitant; // ...
foreach ($team->matches as $match) {
if ($match->pivot->local) {
// put Nice local icon here
} else {
// put Nice visitant icon here
}
}
_