Je termine un grand projet avec Laravel 4 et je devais répondre à toutes les questions que vous vous posez en ce moment. Après avoir lu tous les livres Laravel disponibles sur Leanpub, et des tonnes de googling, j'ai trouvé la structure suivante.
- Une classe Eloquent Model par table datable
- Une classe de référentiel par modèle éloquent
- Une classe de service qui peut communiquer entre plusieurs classes de référentiel.
Alors disons que je construis une base de données de films. J'aurais au moins les classes suivantes de modèle éloquent:
- Film
- Studio
- Réalisateur
- Acteur
- La revue
Une classe de référentiel encapsulerait chaque classe Eloquent Model et serait responsable des opérations CRUD sur la base de données. Les classes du référentiel peuvent ressembler à ceci:
- MovieRepository
- StudioRepository
- DirectorRepository
- ActeurRepository
- ReviewRepository
Chaque classe de référentiel étendrait une classe BaseRepository qui implémente l'interface suivante:
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);
}
Une classe Service est utilisée pour coller plusieurs référentiels ensemble et contient la véritable «logique métier» de l'application. Les contrôleurs communiquent uniquement avec les classes de service pour les actions Créer, Mettre à jour et Supprimer.
Ainsi, lorsque je souhaite créer un nouvel enregistrement de film dans la base de données, ma classe MovieController peut avoir les méthodes suivantes:
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.
}
C'est à vous de déterminer comment vous POSTEZ les données sur vos contrôleurs, mais disons que les données renvoyées par Input :: all () dans la méthode postCreate () ressemblent à ceci:
$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'
)
Étant donné que MovieRepository ne doit pas savoir comment créer des enregistrements Actor, Director ou Studio dans la base de données, nous utiliserons notre classe MovieService, qui pourrait ressembler à ceci:
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;
}
Il nous reste donc une belle séparation judicieuse des préoccupations. Les référentiels ne connaissent que le modèle Eloquent qu'ils insèrent et récupèrent de la base de données. Les contrôleurs ne se soucient pas des référentiels, ils transmettent simplement les données qu'ils collectent auprès de l'utilisateur et les transmettent au service approprié. Le service ne se soucie pas de la manière dont les données qu'il reçoit sont enregistrées dans la base de données, il transmet simplement les données pertinentes qu'il a été fournies par le contrôleur aux référentiels appropriés.