Tôi đang hoàn thành một dự án lớn bằng Laravel 4 và phải trả lời tất cả các câu hỏi bạn đang hỏi ngay bây giờ. Sau khi đọc tất cả các sách Laravel hiện có trên Leanpub và hàng tấn Google Googling, tôi đã nghĩ ra cấu trúc sau.
- Một lớp Mô hình Eloquent cho mỗi bảng có thể dữ liệu
- Một lớp Kho lưu trữ cho mỗi Mô hình Eloquent
- Một lớp Dịch vụ có thể giao tiếp giữa nhiều lớp Kho lưu trữ.
Vì vậy, giả sử tôi đang xây dựng một cơ sở dữ liệu phim. Tôi sẽ có ít nhất các lớp Mô hình Hùng biện sau:
- Bộ phim
- Studio
- Giám đốc
- Diễn viên
- Ôn tập
Một lớp kho lưu trữ sẽ đóng gói từng lớp Eloquent Model và chịu trách nhiệm về các hoạt động CRUD trên cơ sở dữ liệu. Các lớp kho lưu trữ có thể trông giống như sau:
- MovieRepository
- StudioRepository
- DirectorRepository
- ActorRepository
- ReviewRepository
Mỗi lớp kho lưu trữ sẽ mở rộng một lớp BaseRepository triển khai giao diện sau:
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);
}
Một lớp Dịch vụ được sử dụng để gắn nhiều kho lưu trữ lại với nhau và chứa "logic nghiệp vụ" thực của ứng dụng. Bộ điều khiển chỉ giao tiếp với các lớp Dịch vụ cho các hành động Tạo, Cập nhật và Xóa.
Vì vậy, khi tôi muốn tạo một bản ghi Phim mới trong cơ sở dữ liệu, lớp MovieController của tôi có thể có các phương thức sau:
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.
}
Tùy thuộc vào bạn để xác định cách bạn ĐĂNG dữ liệu lên bộ điều khiển của mình, nhưng giả sử dữ liệu được trả về bởi Input :: all () trong phương thức postCreate () trông giống như sau:
$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'
)
Vì MovieRepository không biết cách tạo các bản ghi Actor, Director hoặc Studio trong cơ sở dữ liệu, chúng tôi sẽ sử dụng lớp MovieService của mình, lớp này có thể trông giống như sau:
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;
}
Vì vậy, những gì chúng ta còn lại là một sự tách biệt tốt đẹp, hợp lý của các mối quan tâm. Các kho lưu trữ chỉ biết đến mô hình Eloquent mà chúng chèn và truy xuất từ cơ sở dữ liệu. Bộ điều khiển không quan tâm đến kho lưu trữ, họ chỉ chuyển dữ liệu họ thu thập từ người dùng và chuyển nó đến dịch vụ thích hợp. Dịch vụ không quan tâm dữ liệu nó nhận được lưu vào cơ sở dữ liệu như thế nào , nó chỉ chuyển dữ liệu có liên quan mà bộ điều khiển cung cấp cho các kho lưu trữ thích hợp.