我正在使用 Laravel 4 完成一个大型项目,并且必须回答您现在提出的所有问题。在阅读了 Leanpub 上所有可用的 Laravel 书籍和大量谷歌搜索之后,我想出了以下结构。
- 每个数据表一个 Eloquent Model 类
- 每个 Eloquent 模型一个存储库类
- 可以在多个存储库类之间进行通信的服务类。
假设我正在建立一个电影数据库。我至少会有以下 Eloquent Model 类:
存储库类将封装每个 Eloquent Model 类并负责数据库上的 CRUD 操作。存储库类可能如下所示:
- 电影资料库
- 工作室存储库
- 主任资料库
- 演员库
- 审查存储库
每个存储库类都将扩展一个实现以下接口的 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);
}
服务类用于将多个存储库粘合在一起,并包含应用程序的真正“业务逻辑”。控制器仅与创建、更新和删除操作的服务类通信。
所以当我想在数据库中创建一个新的电影记录时,我的 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.
}
由您决定如何将数据发布到控制器,但假设 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 不应该知道如何在数据库中创建 Actor、Director 或 Studio 记录,我们将使用 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 模型。控制器不关心存储库,他们只是交出从用户那里收集的数据并将其传递给适当的服务。该服务不关心它接收到的数据如何保存到数据库中,它只是将控制器提供的相关数据交给适当的存储库。