私はLaravel 4を使用して大規模なプロジェクトを仕上げており、あなたが今求めているすべての質問に答える必要がありました。Leanpubで入手可能なすべてのLaravelの本、および大量のグーグルを読んだ後、次の構造を思いつきました。
- データブルテーブルごとに1つのEloquent Modelクラス
- Eloquentモデルごとに1つのリポジトリクラス
- 複数のリポジトリクラス間で通信できるサービスクラス。
それでは、映画データベースを構築しているとしましょう。私は少なくとも以下のEloquent Modelクラスを持っています:
リポジトリクラスは、各Eloquentモデルクラスをカプセル化し、データベースでのCRUD操作を担当します。リポジトリクラスは次のようになります。
- MovieRepository
- StudioRepository
- DirectorRepository
- ActorRepository
- ReviewRepository
各リポジトリクラスは、次のインターフェイスを実装するBaseRepositoryクラスを拡張します。
interface BaseRepositoryInterface
{
public function errors();
public function all(array $related = null);
public function get($id, array $related = null);
public function getWhere($column, $value, array $related = null);
public function getRecent($limit, array $related = null);
public function create(array $data);
public function update(array $data);
public function delete($id);
public function deleteWhere($column, $value);
}
Serviceクラスは、複数のリポジトリを結合するために使用され、アプリケーションの実際の「ビジネスロジック」を含みます。コントローラーは、Create、Update、およびDeleteアクションのServiceクラスとのみ通信します。
したがって、データベースに新しいMovieレコードを作成する場合、MovieControllerクラスに次のメソッドが含まれる可能性があります。
public function __construct(MovieRepositoryInterface $movieRepository, MovieServiceInterface $movieService)
{
$this->movieRepository = $movieRepository;
$this->movieService = $movieService;
}
public function postCreate()
{
if( ! $this->movieService->create(Input::all()))
{
return Redirect::back()->withErrors($this->movieService->errors())->withInput();
}
// New movie was saved successfully. Do whatever you need to do here.
}
コントローラーにデータをPOSTする方法を決定するのはあなた次第ですが、postCreate()メソッドのInput :: all()によって返されるデータが次のようになっているとします。
$data = array(
'movie' => array(
'title' => 'Iron Eagle',
'year' => '1986',
'synopsis' => 'When Doug\'s father, an Air Force Pilot, is shot down by MiGs belonging to a radical Middle Eastern state, no one seems able to get him out. Doug finds Chappy, an Air Force Colonel who is intrigued by the idea of sending in two fighters piloted by himself and Doug to rescue Doug\'s father after bombing the MiG base.'
),
'actors' => array(
0 => 'Louis Gossett Jr.',
1 => 'Jason Gedrick',
2 => 'Larry B. Scott'
),
'director' => 'Sidney J. Furie',
'studio' => 'TriStar Pictures'
)
MovieRepositoryは、データベースにアクター、ディレクター、またはスタジオのレコードを作成する方法を認識していないため、次のようなMovieServiceクラスを使用します。
public function __construct(MovieRepositoryInterface $movieRepository, ActorRepositoryInterface $actorRepository, DirectorRepositoryInterface $directorRepository, StudioRepositoryInterface $studioRepository)
{
$this->movieRepository = $movieRepository;
$this->actorRepository = $actorRepository;
$this->directorRepository = $directorRepository;
$this->studioRepository = $studioRepository;
}
public function create(array $input)
{
$movieData = $input['movie'];
$actorsData = $input['actors'];
$directorData = $input['director'];
$studioData = $input['studio'];
// In a more complete example you would probably want to implement database transactions and perform input validation using the Laravel Validator class here.
// Create the new movie record
$movie = $this->movieRepository->create($movieData);
// Create the new actor records and associate them with the movie record
foreach($actors as $actor)
{
$actorModel = $this->actorRepository->create($actor);
$movie->actors()->save($actorModel);
}
// Create the director record and associate it with the movie record
$director = $this->directorRepository->create($directorData);
$director->movies()->associate($movie);
// Create the studio record and associate it with the movie record
$studio = $this->studioRepository->create($studioData);
$studio->movies()->associate($movie);
// Assume everything worked. In the real world you'll need to implement checks.
return true;
}
したがって、私たちが残しているのは、問題を適切に分別することです。リポジトリは、データベースから挿入および取得するEloquentモデルのみを認識します。コントローラはリポジトリを気にせず、ユーザーから収集したデータを引き渡して適切なサービスに渡します。サービスはどうでもいい、受け取ったデータがデータベースに保存される。コントローラーから提供された関連データを適切なリポジトリに渡すだけです。