如何将口才与服务层分离?

Chr*_*ris 8 repository-pattern service-layer laravel eloquent

我正在尝试创建一个干净的服务层,服务层作用于一个或多个存储库,每个存储库都依赖于它自己的雄辩模型.

例如,我可能有:

ForumService
  |
  +-- PostRepo extends PostInterface
  |     |
  |     +-- Post (Eloquent)
  |
  +-- UserRepo extends UserInterface
        |
        +-- User (Eloquent)
Run Code Online (Sandbox Code Playgroud)

每个服务都通过定义它所需的依赖项ioc.所以,像:

// MessageService
// ..
public function __construct(UserInterface $userRepository, 
                            MessageInterface $messageRepository) {
    // ..
}
Run Code Online (Sandbox Code Playgroud)

我的存储库通过它们在各自服务提供商中的绑定来解决,例如:

class UserRepositoryServiceProvider extends ServiceProvider 
{
    public function register()
    {
        $this->app>bind(
            'App\Models\Repositories\User\UserInterface',
            'App\Models\Repositories\User\UserRepository');
    }
}
Run Code Online (Sandbox Code Playgroud)

这一切都很好.每个服务都获得它所需的存储库.

为了使服务层不受任何特定依赖性的影响,任何离开repo的东西都是一个简单的,不可变的数据对象.

日常用语的要点:

  • 只有repo直接与他们自己的模型交谈
  • Repo返回简单,不可变的数据对象
  • 服务将多个repo连接在一起,并将简化的对象呈现给控制器,最终呈现给视图.

但是,我无法associate在服务或回购层为对方雄辩模型提出一个干净的模式.

鉴于Post模型有belongsTo(User::class)关系,我如何在Post存储库层干净地创建该关系.

我试过了:

public function associate($authorId) 
{
    $post->author()->associate($authorId);
}
Run Code Online (Sandbox Code Playgroud)

但是associate期待一个user雄辩的对象,而不仅仅是一个id.我可以:

public function associate($authorId) 
{
    $post->from()->associate($userRepo->findEloquent($authorId));
}
Run Code Online (Sandbox Code Playgroud)

但我觉得我正在将一个雄辩的模型展示成一个不应该采取行动的回购.

Jar*_*zyk 2

最简单的方法:

public function assignToAuthor($postId, $authorId) 
{
    $post = $this->find($postId); // or whatever method you use to find by id

    $post->author_id = $authorId;
}
Run Code Online (Sandbox Code Playgroud)

现在,以上内容意味着您知道author_id关系的外键。为了稍微抽象一下,可以使用:

public function assignToAuthor($postId, $authorId) 
{
    $post = $this->find($postId);

    $foreignKey = $post->author()->getForeignKey();

    $post->{$foreignKey} = $authorId;
}
Run Code Online (Sandbox Code Playgroud)

请注意,您仍然需要save模型$post,但我想您已经知道了。


根据您使用的简单、不可变数据对象的实现,您还可以允许传递对象而不是原始 ID。字里行间的东西:

public function assignToAuthor($postId, $authorId) 
{
    if ($postId instanceof YourDataOject) {
       $postId = $postId->getId();
    }

    if ($authorId instanceof YourDataOject) {
       $authorId = $authorId->getId();
    }

    // ...
}
Run Code Online (Sandbox Code Playgroud)