Zend Framework 2模型中的数据库访问

时间:2013-12-29 10:51:33

标签: php database model zend-framework2

我正在ZF2开发我的应用程序,但尽管尝试了我找不到我的数据库/模型问题的答案。

我认为TableGateway几乎是骨架应用程序示例的副本,作为执行查询任务并返回AdminUser实例的某些类型的AdminUser集合。

这是Module.php的一部分

public function getServiceConfig()
{

    return array(
        'factories' => array(
            'Admin\Model\AdminUserTable' =>  function($sm) {
                $tableGateway = $sm->get('AdminUserTableGateway');
                $table = new AdminUserTable($tableGateway);
                return $table;
            },
            'AdminUserTableGateway' => function ($sm) {
                $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
                $resultSetPrototype = new ResultSet();
                $resultSetPrototype->setArrayObjectPrototype(new AdminUser());
                return new TableGateway('zxf_admin_user', $dbAdapter, null, $resultSetPrototype);
            },
        ),
    );
}

这是控制器

protected $adminUserTable;

public function indexAction()
{
    $this->layout('layout/admin');

    return new ViewModel(array(
        'text' => 'some text',
        'users' => $this->getAdminUserTable()->fetchAll(),
    ));
}

public function getAdminUserTable()
{
    if (!$this->adminUserTable) {
        $sm = $this->getServiceLocator();
        $this->adminUserTable = $sm->get('Admin\Model\AdminUserTable');
    }
    return $this->adminUserTable;
}

我不确定getAdminUserTable方法,这是获取用户的函数

public function getAdminUser($id)
{
    $id  = (int) $id;
    $rowset = $this->tableGateway->select(array('id' => $id));
    $row = $rowset->current();
    if (!$row) {
        throw new \Exception("Could not find row $id");
    }
    return $row;
}

但是如果我有兴趣让另一个类像AdminUserPriviliges这样的对象在你的控制器中执行时会返回

    $user = $this->getAdminUserTable()->getAdminUser($id);

获取权限,即使它们是不同的类,并且它们的数据存储在不同的表中,因此下面的方法需要执行数据库搜索,但因为在AdminUser对象内部它可以使用$ this-> id并且还可以通过AdminUser你可以自己获得权限,这样我就可以根据请求将它们作为一个对象的集合来获取,像这样

    $user_piviliges = $user->getPriviliges();

,内容应该是AdminUserPriviliges实例的集合

    return new ViewModel(array(
        'text' => 'some text',
        'user' => $this->getAdminUserTable()->getAdminUser($id);,
    ));

因此将用户对象发送回视图意味着我们也拥有权限。 以类似的方式,当我移动到其他实体,我希望能够做同样的

喜欢$ product-> getImages()会为你提供所有图像,但当然它们不会存储在同一个表中。

有更好的方法可以做到甚至更简单吗?

1 个答案:

答案 0 :(得分:2)

您的getAdminUserTable和类似功能正在执行服务管理器已经为您完成的工作。默认情况下,在一次请求期间每次调用$sm->get('Admin\Model\AdminUserTable');都将返回相同的对象。 例如,假设我有这项服务:

public function getServiceConfig()
{    
    return array(
            'factories' => array(
                    'TestService' =>  function($sm) {
                        return time();
                    },
            ),
    );
}

我在像这样的控制器动作中使用它:

public function testAction()
{
    $sm = $this->getServiceLocator();
    $first = $sm->get('TestService');
    sleep(1);
    $second = $sm->get('TestService');

    echo $first;
    echo '<br />';
    echo $second;

    return $this->response;
}

如果执行该操作,您将看到打印的两个数字始终相同。这是因为$ first和$ second都指的是第一次调用$sm->get('TestService');时创建的同一个对象。

如果您不想要这种行为,则需要在配置的shared键中指定。

    'shared' => array(
            // Indicate services that should **NOT** be
            // shared -- i.e., ones where you want a different instance
            // every time.
            'TestService' => false,
    )

如果我理解你的其余问题,那么归结为构建自己的域对象并使用控制器中的域对象而不是直接在控制器中使用表格网关。如果是这样,是的,对于任何不仅仅是以直接的方式表示数据库数据的网站来说,这是一个非常好的主意(简单如下:一个电影表转换为一个电影列表页面和一个电影详细信息页面,最小的额外逻辑。)

请注意,您最终不会以超出需要的方式加载更多数据。例如,用户可能不是一个非常重的对象,将至少当前用户的所有数据加载到对象中可能是有意义的。但是,假设您有一个Product表链接到数据库中的大多数其他表(产品信息,运输信息,组件......)。您可能希望避免将所有信息都放在对象中,如果你真正做的只是提供产品名称列表。

在回复评论时编辑

那么你的问题到底是什么?如何在User类中实现类似getProfiles的方法?你可以做类似

的事情
public function getPrivileges() {
    $privTable = new TableGateway('PRIVILEGES', $adapter);
    $rowset = $privTable->select(array('USER' => $this->id));
    $privileges = array();

    foreach ($rowset as $row) {
        $priv = new Privilege;
        $priv.setType($row['TYPE']);
        //...set other properties
        $privileges[] = $priv;
    }

    return $privileges;
}

或者,如果您需要从多个表中获取信息,则不要使用TableGateway,而是构建自己的Zend Sql / Select对象,您可以自由添加任何联接,等等。 {3}}