將數據庫訪問權移動到單獨的類會帶來一些優勢。首先,如果您將數據庫訪問與其他邏輯分開,則可以更輕鬆地替換數據庫訪問的實現。如果出於某種原因想要放棄Doctrine DBAL,您會很高興所有的代碼都只是引用某個存儲庫接口,而不是直接查詢數據庫。
第二大優勢是您可以在分離數據庫訪問邏輯時測試您的應用程序邏輯。如果您爲UserService內的用戶注入一個Repository,則可以在測試中對此進行模擬,並確保只有在實際應用邏輯出現問題時纔會失敗。
的你可以做什麼
接口一個小例子是便於在整個代碼庫的參考。沒有代碼引用實現,只有接口。這樣,你可以很容易地更換接口的實現不接觸它使用的所有地方:
interface IUserRepository
{
/**
* @return User
*/
public function getUserById($userId);
}
當然,你需要的實現所述接口。這是你注入你的UserService的內容。這是你有一天可能會用接口的另一個實現替換:
class DoctrineDBALUserRepository implements IUserRepository
{
/**
* @return User
*/
public function getUserById($userId)
{
//implementation specific for Doctrine DBAL
}
}
UserService只知道接口,可以自由使用它。爲了避免必須在代碼中的很多地方注入UserRepository,您可以創建一個便捷的構建方法。請注意,引用接口並注入該接口的實施構建方法構造:在地方,你可以編寫業務邏輯測試
class UserService
{
private $UserRepository;
public static build()
{
return new UserService(new DoctrineDBALUserRepository());
}
public function __construct(IUserRepository $UserRepository)
{
$this->UserRepository = $UserRepository;
}
public function getUserById($userId)
{
if ($User = $this->UserRepository->getUserById($userId) {
return $User;
}
throw new RuntimeException('O noes, we messed up');
}
有了這個(例如,如果無法保存,將拋出一個異常):
public function UserServiceTest extends PHPUnit_Framework_TestCase
{
public function testGetUserById_whenRetrievingFails_shouldThrowAnException()
{
$RepositoryStub = $this->getMock('IUserRepository');
$RepositoryStub->expects($this->any())->method('getUserById')->will($this->returnValue(false);
$UserService = new UserService($RepositoryStub);
$this->setExpectedException('RuntimeException');
$UserService->getUserById(1);
}
}
我可以想象如果你還沒有進入單元測試,你對代碼的最後一點不熟悉。我希望你是,如果不敦促你也讀一下:D我認爲無論如何,答案的完整性都包括它是有益的。
哇,謝謝!我還沒有進入測試階段,但我已經閱讀了很多,並意識到這是我需要做的。 – itsmequinn