2015-05-11 70 views
8

我正在嘗試創建一個乾淨的服務層,其中服務層作用於一個或多個存儲庫,並且每個存儲庫都在其自己的雄辯模型上運行。如何從服務層分離雄辯?

例如,我可以具有:

ForumService 
    | 
    +-- PostRepo extends PostInterface 
    |  | 
    |  +-- Post (Eloquent) 
    | 
    +-- UserRepo extends UserInterface 
     | 
     +-- User (Eloquent) 

每個服務定義它經由ioc需要的依賴。所以,像這樣:

// MessageService 
// .. 
public function __construct(UserInterface $userRepository, 
          MessageInterface $messageRepository) { 
    // .. 
} 

我的倉庫通過其綁定在各自的服務供應商解決,如:

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

這一切工作就好了。每個服務都可以獲得它需要的存儲庫。

爲了使服務層不受任何依賴於雄辯的影響,任何留下回購的東西都是一個簡單的,不可變的數據對象。

在日常語言要點:

  • 只有回購的談話,以自己的模式直接
  • 回購迴歸簡單的,一成不變的,數據對象
  • 服務行動,以配合多種回購的一起和現在簡化的對象返回到控制器,最終還是視圖。

然而我不能想出的服務或回購層乾淨的模式associate雄辯模型給對方。

鑑於Post模型具有belongsTo(User::class)關係,我如何在Post存儲庫層乾淨地創建該關係。

我曾嘗試:

public function associate($authorId) 
{ 
    $post->author()->associate($authorId); 
} 

associate期望一個user雄辯的對象,而不僅僅是一個ID。我可以這樣做:

public function associate($authorId) 
{ 
    $post->from()->associate($userRepo->findEloquent($authorId)); 
} 

但我覺得我正在浮出水面模型,進入一個不應該作用於其上的回購。

+0

那麼您還有什麼問題嗎?或者答案是你問的? –

回答

2

最簡單的辦法:

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

    $post->author_id = $authorId; 
} 

現在,上面意味着你知道關係的外鍵author_id。爲了抽象的,它只是一個位,使用此:

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

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

    $post->{$foreignKey} = $authorId; 
} 

記住,你仍然需要save$post模式,但我想你已經知道了。


根據您的實現的簡單的,不可改變的,數據對象你使用,你也可以讓傳遞對象,而不是原始的ID。線之間的東西:

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

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

    // ... 
} 
2

我在這帶來了一些理智這種情況對我過去所做的是什麼做的事情類似於你在你的第二個associate方法做,並與Eloquent前綴的倉庫,所以在事件中,我使用的東西,除了Eloquent,我只是創建了一個新的倉庫實現。

所以在這種情況下,我最終會得到class EloquentUserRepository implements UserInterface。我通常最終會得到一些公共方法,這些方法只返回原語,並且可能還有一些私有方法,這些方法會與Eloquent耦合,因此我最終做的是將這些公共方法放到AbstractUserRepository中,或者如果它更有意義,保持代碼乾爽。

2

這真的取決於情況,我對這些行爲以及我的知識庫有很多想法。

我的建議是乾脆不使用「聯想」功能,你可以簡單地做:

$post->user_id = $userID; 
$post->save(); 

**當然,你需要確保與ID的用戶存在。

A)可以與「associatingUser」 B)你可以做你喜歡使用的UserRepositoryInterface, 我看不出有什麼問題,添加接口作爲依賴做了一個特殊的服務之外做。

選項A:

class AssociateUserToPost { 

private $userRepo; 
private $postRepo; 

public function __construct(UserRepoInterface $userRepo, PostRepoInterface $postRepo) { 
    $this->userRepo = $userRepo; 
    $this->postRepo = $postRepo; 
} 

public function associate($userId, $postId) { 
    $user = $this->userRepo->getUser($userId); 
    if (! $user) 
     throw new UserNotExistException(); 

    $post = $this->postRepo->getPost($postId); 
    if (! $post) 
     throw new PostNotExistException(); 

    $this->postRepo->AttachUserToPost($postId, $userId); 
} 

} 

選項B(不太一樣,代碼只是坐在在不同的地方)

class PostRepository implements PostRepoInterface { 

private $userRepo; 

public function __construct(UserRepoInterface $userRepo) { 
    $this->userRepo = $userRepo; 
} 

public function associate($userId, $postId) { 
    $user = $this->userRepo->getUser($userId); 
    if (! $user) 
     throw new UserNotExistException(); 

    $post = $this->getPost($postId); 
    if (! $post) 
     throw new PostNotExistException(); 

    $this->AttachUserToPost($postId, $userId); 
} 

} 
0

水合!

我假設在post服務中調用findEloquent的另一個原因看起來很糟糕,因爲您可能已經在控制器中檢索到該數據。簡而言之,您可以訪問Eloquent用於將原始查詢結果轉換爲功能完備的模型的相同方法。

$userData = array(
    // simple, immutable data 
); 

$userCollection = User::hydrate(array($userData)); 

$userModel = $userCollection->first(); 
0

我想你實際上需要一個額外的層,就是我所說的管理者。這將包含所有的業務邏輯,並且只能用於接口。在引擎蓋下,它會調用服務(每個知道使用特定的資源/模型)