Thắc mắc về Repository trong laravel
Tôi có thêm 1 vài repository vào AppServiceProvider như sau:
public function register()
{
$this->app->bind(UsersRepositoryInterface::class, UsersRepository::class);
$this->app->bind(CoursesRepositoryInterface::class, CoursesRepository::class);
$this->app->bind(PostsRepositoryInterface::class, PostsRepository::class);
}
Nhưng điều tôi thắc mắc là khi tôi không thêm vào thì code vẫn chạy bình thường. vậy tại sao tôi cần thêm chúng. Xin cảm ơn.
4 CÂU TRẢ LỜI
Check comment của chủ tus thì có thể thấy, bạn chỉ dùng UserRepository chứ ko phải là UserRepositoryInterface. ở constructor. Điều này có nghĩa là bạn đang thông báo cho App laravel 1 cái implement cụ thể, và App sẽ tự tạo ra cho bạn 1 Repository cho bạn, như cách mà bạn xài Request hay Model.
Ở AppSerivceProvider
$this->app->bind(
\App\Services\Company\ICompanyService::class,
\App\Services\Company\VnCompanyService::class
);
Là nơi bạn sẽ khai những service sẽ được nạp vào app lúc boot lên. Laravel có cái hay là khi bạn khai báo 1 interface và 1 implement của nó, thì nơi nào cần bind interface đó nó sẽ gọi đến implement của nó.
protected ICompanyService $companyService;
public function __construct(ICompanyService $companyService)
{
$this->companyService = $companyService;
}
public function getList(Request $request)
{
$response = $this->companyService->getCompaniesInfoList($request);
return $this->responseArray($response);
}
Điều này có ý nghĩa, khi ở controller bạn sẽ sử dụng interface để tương tác chứ ko dùng implemnt trực tiếp. Vd nhé. Như cách của bạn mình sẽ bind trực tiếp VnCompanyService vào controller. như thế này:
protected VnCompanyService $companyService;
public function __construct(VnCompanyService $companyService)
{
$this->companyService = $companyService;
}
public function getList(Request $request)
{
$response = $this->companyService->getCompaniesInfoList($request);
return $this->responseArray($response);
}
Tuy nhiên 1 ngày nào đó, sếp kêu mình đổi lại để xài cho các cty ở Japan và mình tạo ra 1 service là JaCompanySerivce. và việc mình cần làm là đổi hết bất cứ chỗ nào là Vn -> Ja. oh no, đổi quá nhiều chỗ. và còn nguy hiểm nữa
protected JaCompanyService $companyService;
public function __construct(JaCompanyService $companyService)
{
$this->companyService = $companyService;
}
public function getList(Request $request)
{
$response = $this->companyService->getCompaniesInfoList($request);
return $this->responseArray($response);
}
Nếu ta dùng binding trong appService ta chỉ cần thay
$this->app->bind(
\App\Services\Company\ICompanyService::class,
\App\Services\Company\JaCompanyService::class
);
là xong. quá đã đúng ko, check thêm doc ở đây: https://laravel.com/docs/10.x/container#binding-interfaces-to-implementations
RẤT CHI TIẾT, CẢM ƠN BẠN.
Để khi bạn thay đổi UsersRepository
hay PostsRepository
khác thì chỉ cần thay đổi ở trong AppServiceProvider
mà không cần truy cập đến controller để thay đổi
cái này để bind tới repository, khi DI dùng Interface thì nó sẽ biết là cần dùng cái nào
ví dụ:
public function __construct(UsersRepositoryInterface $usersRepositoryInterface) { $this->usersRepositoryInterface = $usersRepositoryInterface; }
như này nó sẽ lấy đc ra UsersRepository, còn nếu bạn để
public function __construct(UsersRepository $usersRepository) { $this->usersRepository = $usersRepository; }
thì chẳng cần register cũng chạy đc
Đúng là mình dùng cách này
public function __construct(UsersRepository $usersRepository) { $this->usersRepository = $usersRepository; }
Nên nó vẫn chạy bt thật. nhưng không hiểu ở hai cách này thì nó có ưu nhược điểm gì không. (về hiệu năng). Thanks