首先呢,大家应该先了解一下什么是Laravel的控制反转和依赖注入还有就是Laravel的内核ioc容器,因为Repository会用到很多这方面的思想,本文会讲解一切这方面的知识(主要就是陈述大概意思,这样能更好的理解Repository),只不过是笔者自身的理解,如有更深的疑问,请关注笔者,后续会给大家呈现出来。那么咱们就切入正题!!!!
首先申明一下,如果不使用这个Repository(工厂)也可以,实现Model和Controller分层也行,笔者建议最好用Laravel的Eloquent orm,因为这个真的非常强大(想要更多的了解Eloquent,也请大家稍安勿躁,网上也会有很多这样的解释,笔者近期会给大家好好的写一个Eloquent解析的)。但是Laravel是一个高度解耦的框架,内核本身就是Ioc控制反转(Inversion of Control,缩写为IoC)也叫容器,为了是代码之间更加的解耦,就有了控制反转和依赖注入。
由于本文主要讲解Repository模式,所以控制反转和依赖注入还有IOC容器笔者将会用自己理解的陈述给大家(有点墨迹了,嘿嘿,稍安勿躁)。
控制反转:
控制反转(Inversion of Control,缩写为IoC):控制反转是将组件间的依赖关系从程序内部提到外部来管理。也就是说:假如,有一个A.php这个类(Controller层),一般情况下可以在这个A类里进行实例化,但是我们要注意它的解耦度,所以我在外面任意的一个地方来写这个实例化的B对象(model),然后在A类里面进行调用即可。这就是控制反转,这样使代码更加解耦,看着也更清爽,简洁,舒服。
依赖注入
依赖注入(Dependency Injection,简称DI):其实依赖注入和控制反转大致差不多,可以说一样,也就是说依赖注入只不过是控制反转的一种形式,大体和控制反转非常相似,只是这个A类接收的B对象是一个参数,因为不在A类里面实例化,所以只是传入即可(传参)。
ioc容器
Laravel ioc容器:其实就是控制反转IOC容器,也就是说它是全能,因为依赖注入只是控制反转的一种形式,而控制反转是IOC容器,同时他们都是对代码进行解耦,降低耦合度的一种面向对象的设计模式。用bind和make就能搞定。
Laravel可以用Composer来引入很多第三方插件辅助的进行项目开发,我也用到了很多,都是现在provider数组里进行注册(IOC思想),然后就怎样怎样的(嘿嘿,突然忘记了)
以上纯属个人理解,没有运用大牛的官话
那么,正文开始…
为了保持代码的整洁性和可读性,使用Repository Pattern 是非常有用的。事实上,我们也不必仅仅为了使用这个特别的设计模式去使用Laravel,然而在下面的场景下,我们将使用OOP的框架Laravel 去展示如何使用repositories 使我们的Controller层不再那么啰嗦、更加解耦和易读。下面让我们更深入的研究一下。
其实使用Repositories并不是必要的,在你的应用中你完全可以不使用这个设计模式的前提下完成绝大多数的事情,然而随着时间的推移你可能把自己陷入一个死角,比如不选择使用Repositories会使你的应用测试很不容易,(swapping out implementations)具体的实现将会变的很复杂,下面我们看一个例子。
//HousesController.php
class HousesController extends BaseController {
public function index()
{
$houses = House::all();
return View::make('houses.index',compact('houses'));
}
public function create()
{
return View::make('houses.create');
}
public function show($id)
{
$house = House::find($id);
return View::make('houses.show',compact('house'));
}
}
这是一个很典型的一段代码使用Eloquent和数据库交互,这段代码工作的很正常,但是controller层对于Eloquent而言将是紧耦合的。在此我们可以注入一个repository创建一个解耦类型的代码版本,这个解耦的版本代码可以使后续程序的具体实现更加简单。
其实完成整个repository模式需要相当多的步骤,但是一旦你完成几次就会自然而然变成了一种习惯了,下面我们将详细介绍每一步。
1.创建 Repository 文件夹
首先我们需要在app文件夹创建自己Repository 文件夹repositories(类似于Model,也可以说这就是个Model,哈哈),然后文件夹的每一个文件都要设置相应的命名空间。(这是重点,笔者就曾经进过忘记设置相应的命名空间的坑,悔恨中…)
2: 创建相应的 Interface类
第二步创建对应的接口,其决定着我们的repository类必须要实现的相关方法,如下例所示,在此再次强调的是命名空间一定要记得加上
(简单来说就是因为这个接口类决定了和Controller层相关系的工厂类(Repository)里面的方法到底存在不存在)。
//HouseRepositoryInterface.php (文件名)
namespace App\Repositories;
interface HouseRepositoryInterface {
public function selectAll();
public function find($id);
}
3:创建对应的 Repository类
现在我们可以创建我们repository类 来给我们干活了,在这个类文件中我们可以把我们的绝大多数的数据库查询都放进去,不论多么复杂。
(创建一个DBRepository工厂类,具体的逻辑在这里写就可以了,和数据库互动在这里写就可以)
//DbHouseRepository.php (文件名)
namespace App\Repositories;
use House;
class DbHouseRepository implements HouseRepositoryInterface {
public function selectAll()
{
return House::all();
}
public function find($id)
{
return House::find($id);
}
}
4:创建后端服务提供
首先你需要理解所谓服务提供,请参考手册服务提供者(注册服务)
(创建后端的服务提供者了,这个的话得先说说Laravel框架的核心了,因为Laravel框架的核心时IOC容器,说到IOC容器就得说到控制反转和依赖注入了,前面大家大概应经了解了吧,笔者想的也挺周到吧,啦啦啦)
//BackendServiceProvider.php (文件名)
namespace App\Repositories;
use IlluminateSupportSeriveProvider;
class BackSerivePrivider extends ServiceProvider {
public function register()
{
$this->app->bind(
'App\Repositories\HouseRepositoryInterface',
'App\Repositories\DbHouseRepository');
}
}
当然你也可以新建一个文件夹主要放我们的provider相关文件。
上面一段代码主要说的是,当你在controller层使用类型提示HouseRepositoryInterface,我们知道你将会使用DbHouseRepository.
5:更新你的Providers Array
其实在上面的代码中,我们已经实现了一个依赖注入,但如果我们要使用在此我们是需要手动去写的,为了更为方面,我们需要增加这个providers 到app/config/app.php 中的 providers数组里面,只需要在最后加上
App\Repositories\BackendServiceProvider::class,
6:最后使用依赖注入更新你的controller
当我们完成上面的那些内容之后,我们在Controller只需要简单的调用方法代替之前的复杂的数据库调用,如下面内容:
//HousesController.php (文件名)
use App\repositories\HouseRepositoryInterface;
class HousesController extends BaseController {
protected $house;
public function __construct(HouseRepositoryInterface $house)
{
$this->house = $house;
}
public function index()
{
$houses = $this->house->selectAll();
return View::make('houses.index', compact('houses'));
}
public function create()
{
return View::make('houses.create');
}
public function show($id)
{
$house = $this->house->find($id);
return View::make('houses.show', compact('house'));
}
}
这样 整个模式的转换就完成了。
是不是更加解耦了呢,如果是的话请给一个小赞赞吧,感谢鉴赏,诸君晚安.
本文也是参考了一些文章并且是笔者日常积累所得,所以在深夜里亲自手敲了一份,为的目的就是能和大家一起成长,也希望此篇文章会给大家带来收获,谢谢大家。