我在 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);
},
),
);
}
这是 Controller
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 的类,当您在 Controller 中执行此操作时将返回对象
$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);,
));
因此将用户对象发送回 View 将意味着我们也拥有特权。 以类似的方式,当我搬到其他实体时,我希望能够做同样的事情
像 $product->getImages() 会为您提供所有图像,但它们当然不会存储在同一个表中。
是否有更好或更简单的方法?
最佳答案
您的 getAdminUserTable
和类似功能正在执行服务管理器已经为您完成的工作。默认情况下,在一个请求期间每次调用 $sm->get('Admin\Model\AdminUserTable');
都会返回相同的对象。
例如,假设我有这项服务:
public function getServiceConfig()
{
return array(
'factories' => array(
'TestService' => function($sm) {
return time();
},
),
);
}
我在这样的 Controller 操作中使用它:
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,
)
如果我理解你的问题的其余部分,它归结为构建你自己的域对象并在 Controller 中使用它们,而不是直接在 Controller 中使用你的表网关。如果是这样,是的,对于任何不仅仅以直接方式表示数据库数据的站点来说,这都是一个非常好的主意(直接如下:一个电影表转换为一个电影列表页面和一个电影详细信息页面,只需最少的额外逻辑).
请注意,您最终加载的数据不会超出您的需要。例如,用户可能不是一个很重的对象,将至少当前用户的所有数据加载到一个对象中可能是有意义的。但是假设您有一个产品表链接到数据库中的大多数其他表(产品信息、运输信息、组件...)。如果您真正要做的只是展示产品名称列表,那么您可能希望避免将所有这些信息放入一个对象中。
根据评论进行编辑
那么您的问题到底是什么?如何在 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 对象,您可以在其中自由添加任何连接、wheres 等。参见 http://zf2.readthedocs.org/en/latest/modules/zend.db.sql.html .
关于php - Zend Framework 2 模型中的数据库访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20824362/