使用Zend Framework利用多个数据源

时间:2012-10-26 10:36:24

标签: php oop zend-framework zend-db

我正在启动一个基于zend框架构建的应用程序;此应用程序应该能够使用除数据库之外的多个数据源;例如,一个网络服务。

我一直在阅读如何构建我的模型以便允许这种情况。我遇到过似乎提供解决方案的各种概念(DataMapper模式,服务模式,适配器层等)。但是,我仍然对如何将这些内容整合到一个可重用且可扩展的代码库中感到困惑。

之前我使用过zend框架,通常使用mysql表。例如,我有一个Users表...我简单地在我的模型中有一个Users类,它包含用户域的业务逻辑和一个扩展Zend_Db_Table_Row_Abstract的User类,表示用户表中的一行。

我如何最好地组织我的模型和代码库,这样我仍然可以调用$ users-> fetchAll()并获取用户对象的集合,而不管我的数据源是什么?

1 个答案:

答案 0 :(得分:4)

它基本上与您之前的工作方式相同,只是使用Zend_Db_Table_Gateway代替My_UserGateway_Whatever,例如首先创建一个接口:

interface UserGateway
{
    /**
     * @return array
     * @throws UserGatewayException
     */
    public function findAll();
}

我们不希望具体网关中的异常出现在消费代码中,因此我们将UserGatewayException添加为catch all:

 class UserGatewayException extends RuntimeException
 {}

然后添加一个实现该接口的类:

class My_UserGateway_Webservice implements UserGateway
{
    public function findAll()
    {
        try {
            // insert logic to fetch from the webservice
            return $userData;
        } catch (Exception $e) {
            throw new UserGatewayException($e->getMessage(), $e->getCode, $e);
        }
    }

    // … more code
}

同样,如果要使用数据库源,可以为Zend_Db_ *类编写适配器,例如

class My_UserGateway_Database implements UserGateway
{
    private $tableDataGateway;

    public function __construct(Zend_Db_Table_Abstract $tableDataGateway)
    {
        $this->tableDataGateway = $tableDataGateway;
    }

    public function findAll()
    {
        try {
            return $this->tableDataGateway->select()->blah();
        } catch (Exception $e) {
            throw new UserGatewayException($e->getMessage(), $e->getCode, $e);
        }
    }

    // … more code
}

如果您需要其他数据提供程序,请确保它们实现该接口,因此您可以依赖findAll方法。使您的消费类依赖于界面,例如

class SomethingUsingUsers
{
    private $userGateway;

    public function __construct(UserGateway $userGateway)
    {
        $this->userGateway = $userGateway;
    }

    public function something()
    {
        try {
            $users = $this->userGateway->findAll();
            // do something with array of user data from gateway
        } catch (UserGatewayException $e) {
            // handle Exception
        }
    }

    // … more code
}

现在,当您创建SomethingUsingUsers时,您可以轻松地将一个或另一个网关注入构造函数,无论您使用哪个网关,您的代码都将正常工作:

$foo = SomethingUsingUsers(
    new My_UserGateway_Database(
        new Zend_Db_Table('User')
    )
)

或者,对于Webservice:

$foo = SomethingUsingUsers(
    new My_UserGateway_Webservice(
        // any additional dependencies
    )
)