I am attempting to create a clean cut service layer, whereby the service layer acts upon one or more repositories, and each repositories acts on its own eloquent model.
For example, I may have:
ForumService
|
+-- PostRepo extends PostInterface
| |
| +-- Post (Eloquent)
|
+-- UserRepo extends UserInterface
|
+-- User (Eloquent)
Each service defines it's required dependencies via ioc
. So, something like:
// MessageService
// ..
public function __construct(UserInterface $userRepository,
MessageInterface $messageRepository) {
// ..
}
My repositories are resolved via their bindings in their respective service providers, such as:
class UserRepositoryServiceProvider extends ServiceProvider
{
public function register()
{
$this->app>bind(
'App\Models\Repositories\User\UserInterface',
'App\Models\Repositories\User\UserRepository');
}
}
This all works just fine. Each service gets the repositories it requires.
To keep the service layer clear of any specific dependency on eloquent, anything that leaves a repo is a simple, immutable, data object.
Key points in everyday language:
- Only the repo's talk to their own models directly
- Repo's return simple, immutable, data objects
- Services act to tie multiple repo's together and present simplified objects back to the controllers, and ultimately the views.
However I can't come up with a clean pattern to associate
eloquent models to each other at the service or repo layer.
Given the Post
model has a belongsTo(User::class)
relationship, how do I cleanly create that relationship at the Post
repository layer.
I have tried:
public function associate($authorId)
{
$post->author()->associate($authorId);
}
But associate
expects a user
eloquent object, not just an id. I could do:
public function associate($authorId)
{
$post->from()->associate($userRepo->findEloquent($authorId));
}
But I feel like I am surfacing a eloquent model up into a repo that shouldn't be acting on it.