From Apprentice To Artisan 01

Dependency Injection 依赖注入


laravel 框架的基础是:IoC Container (控制反转容器)、控制反转的"容器” 是方便实现“依赖注入”的工具、但实现依赖注入并不一定需要控制反转容器、只是使用“容器”会方便和容易一点


#控制反转

class UserController extends BaseController{
    public function getIndex()
    {
        $users= User::all();
        return View::make('users.index', compact('users'));
    }
}

如果测试這段代码就需跟实际的数据库发生联系、即Eloquent ORM 跟改控制器有紧耦合,违背了“关注分离”软件设计的原则、简单讲:這个控制器知道太多了。

控制器不需要了解数据从哪里来,只知道如何访问、和这数据是可用的即可

    Separation Of Concerns    关注分离

    Every class should have a single responsibility, and that responsibility should be entirely encapsulated by the class.

    每一个类都应该有单独的职责,并且该职责应完全被这个类封装。(译者注:我认为就是不要让多个类负责同样的职责)

“关注分离”的好处就是让Web 控制器和数据访问解耦、這样使得实现存储迁移更容易、测试也更容易!"Web"在你的应用中就紧紧作为一个传输层!

例如:一台显示器、用很多连接的线缆接口(HDMI、VGA、DVI)、你可以通过不同的接口访问该显示器的功能。Internet  就像一个线缆连接你的应用程序、大部分显示器的功能是独立于线缆的,线缆(比如 HTTP)只是你应用程序的一种传输机制、所以不想把传输机制(控制器)和业务逻辑混在一起。這样的好处就是其他的传输机制比如:API调用、移动应用等都可以访问我们的业务逻辑


所以就别把控制器和Eloquent ORM 耦合在一起了,咱们添加(注入)一个 Repository 类


#建立协议

定义一个接口、然后实现它

interface UserRepositoryInterface
{
    public function all();
}
   
class DbUserRepository implements UserRepositoryInterface
{
    public function all()
    {
        return User::all()->toArray();
    }
}

#然后就将改该接口的“实现” 添加(注入)到我们的控制器中

class UserController extends BaseController
{
    public function __construct(UserRepositoryInterface $users)
    {
        $this->users = $users;
    }
   
    public function getIndex()
    {
        $users=$this->users->all();
        return View::make('users.index', compact('users'));
    }
}
這样控制跟数据层面就无关了,无知就是福!数据可能来之MySql、MongoDB 或者Redis 、控制器不知道也不关注他们的区别、這个小小的改变就让web 层独立 Data 层,将来切换存储也很容易.

#写一个测试案例、首先模拟一个Repository 和绑定它到 应用 IoC 容器中、然后要保证控制器正确的调用這个Repository(数据仓库)

public function testIndexActionBindsUsersFromRepository()
    {    
        // Arrange...
        $repository = Mockery::mock('UserRepositoryInterface');
        $repository->shouldReceive('all')->once()->andReturn(array('foo'));
        App::instance('UserRepositoryInterface', $repository);
        // Act...
        $response  = $this->action('GET', 'UserController@getIndex');
         
        // Assert...
        $this->assertResponseOk();
        $this->assertViewHas('users', array('foo'));
    }

#mockery 插件

    Are you Mocking Me 你在模仿我么?

    In this example, we used the `Mockery` mocking library. This library provides a clean, expressive interface for mocking your classes. Mockery can be easily insalled via Composer.

    在上面的例子里, 我们使用了名为`Mockery`的模仿库。 这个库提供了一套整洁且富有表达力的方法,用来模仿你写的类。 Mockery可以通过Composer安装。

该文章只是个人笔记、原文参照:http://my.oschina.net/zgldh/blog/300008#OSC_h2_1

你可能感兴趣的:(From Apprentice To Artisan 01)