Zend framework2 带有子模型的Zend\Db模型
ZF2项目-无条令,使用本机Zend\Db:具有以下结构:Zend framework2 带有子模型的Zend\Db模型,zend-framework2,parent-child,zend-db,one-to-one,Zend Framework2,Parent Child,Zend Db,One To One,ZF2项目-无条令,使用本机Zend\Db:具有以下结构: Controller ProductController Model Product ProductTable ProductType ProductTypeTable Product是模型,具有与“products”表字段相对应的变量 ProductTable是通过tableGateway连接到数据库的表类。ProductTable具有getItem()方法,可通过“id”检索请求的产品 P
Controller
ProductController
Model
Product
ProductTable
ProductType
ProductTypeTable
Product是模型,具有与“products”表字段相对应的变量
ProductTable是通过tableGateway连接到数据库的表类。ProductTable具有getItem()方法,可通过“id”检索请求的产品
ProductType是模型,具有与“productTypes”表字段相对应的id、name、description等变量
ProductTypeTable和ProductTable一样是table类
每种产品都属于特定的产品类型
products.productTypeId = productTypes.id
这就是关系
在ProductTable->getItem()方法中,我可以简单地获取productTypeId。
我可以使用联接从“productTypes”表中获取productTypes.name、productTypes.description或任何字段。
但我不想这样做-而是处理产品实体中的新变量,如productTypeName、productTypeDesc、,
我想使用Product->getProductType()
并将其设置为ProductType对象,这样我就可以获取Product->getProductType()->>getName()
来获取产品类型名称
我只想指定一个子模型作为父模型的变量
我可以在控制器中执行此操作,如下所示:
$product = $this->getProductTable()->getItem(7); // id = 7
$product->setProductType($this->getProductTypeTable()
->getItem($product->getProductTypeId());
但是我想在产品表类getItem()方法中实现它,所以我不必在每个控制器中都考虑它,它是一种封装的
正确的方法是什么
谢谢。要做到这一点,只需遵循以下3个步骤:
产品->exchangeArray()
功能更智能ProductType
字段,例如:type
@var-ProductType
,这样您就有了适当的自动补偿(在Eclipse中适用于我)
您遇到的问题是,在将数据库访问抽象到单个数据库表方面,它实际上是唯一擅长的。它无论如何都不允许实体水合或关系管理。对象关系映射器(ORM)如条令解决了这个问题
如果原则,无论出于何种原因,不适合您的用例,那么替代方案可以是实现
数据映射器是一个将内存中的对象与数据库分离的软件层。它的职责是在两者之间传输数据,并将它们彼此隔离
数据映射器将使用表网关获取每个表所需的数据,并构造产品
实例,包括其关联的产品类型
。然后将映射器公开给控制器(而不是表网关)
ProductMapper
的一个简单示例
class ProductMapper
{
// @var \Zend\Db\TableGateway\TableGateway
protected $productTable;
protected $productTypeMapper;
// an 'identity map' of loaded products
protected $loaded = [];
public function __construct(ProductTable $productTable, ProductTypeMapper $productTypeMapper)
{
$this->productTable = $productTable;
$this->productTypeMapper = $productTypeMapper;
}
protected function hydrate(Product $product, array $data)
{
$product->setId($data['id']);
$product->setName($data['name']);
$product->setFoo($data['foo']);
if (isset($data['type_id'])) {
// Load a fully constructed product type from the database
$type = $this->productTypeMapper->findById($data['type_id']);
$product->setType($type);
}
return $product;
}
public function findById($id)
{
if (isset($this->loaded[$id])) {
return $this->loaded[$id];
}
// Get the data
$row = $this->productTable->select(['id' => $id]);
if (empty($row)) {
throw new SomeCustomException("No product could be found with id $id");
}
// Create and hydrate the product
$product = $this->hydrate(new Product, $row->current())
$this->loaded[$id] = $product;
return $product;
}
public function save(array $data);
public function update($data);
public function delete($id);
}
感谢您的详细回复。不过,我正在成功地使用联接进行此操作,这正是我试图避免的。我不想填充ProductType对象,我想通过产品附带的productTypeId字段值创建相关的ProductType对象实例,并将其作为对象变量链接到产品模型。谢谢。这是真实的就我所能理解你的详细描述而言,这很好。这很好,因为我知道一定有办法,但我对ZF2不是100%熟悉。我试图避免使用本地方法进行学习。我目前无法对其进行测试,但我想感谢你为解释这一点所做的努力。我回来后会给出结果这个周末我对我的电脑做了一些关于DataMapper的研究,我知道这是我需要的,也是我必须学习的。但是我太专注于TableGateway了——这意味着到目前为止我只熟悉ZF2中的TableGateway模式,没有适当的文档,我很难开始,我发现只有DataMapper但是另一个对初学者没有帮助的大画面的一小部分。你能参考一个教程或一个我可以像传统指南一样遵循的好的开始吗?除此之外,据我所知,DataMapper正是我问题的答案。谢谢!我强烈推荐Martin Fowler的书。尽管这本书第一次出版在2002年,大多数示例都是Java,它仍然提供了关于web应用程序设计模式的非常相关和简洁的细节(数据映射器模式只是众多模式中的一种)。我会尝试一下-我不认为它对ZF2有太大帮助,但它看起来像是了解很多模式的宝贵资源-我不是很强。谢谢。关于您的示例ProductMapper和我的问题中的文件结构,以及您的声明“您将在控制器中而不是在表网关中公开映射器”:我是否打算杀掉ProductTable和ProductTypeTable类,注册映射器类,并使用它们来代替表类?我可以感觉到我在问一个ZF2专家的愚蠢问题,但我非常习惯使用Album Tutorial约定来设置表网关,并在Module.php中作为工厂返回,现在我只是尝试跟随一个有组织的方式就像专辑教程一样。再次感谢。
class ProductMapper
{
// @var \Zend\Db\TableGateway\TableGateway
protected $productTable;
protected $productTypeMapper;
// an 'identity map' of loaded products
protected $loaded = [];
public function __construct(ProductTable $productTable, ProductTypeMapper $productTypeMapper)
{
$this->productTable = $productTable;
$this->productTypeMapper = $productTypeMapper;
}
protected function hydrate(Product $product, array $data)
{
$product->setId($data['id']);
$product->setName($data['name']);
$product->setFoo($data['foo']);
if (isset($data['type_id'])) {
// Load a fully constructed product type from the database
$type = $this->productTypeMapper->findById($data['type_id']);
$product->setType($type);
}
return $product;
}
public function findById($id)
{
if (isset($this->loaded[$id])) {
return $this->loaded[$id];
}
// Get the data
$row = $this->productTable->select(['id' => $id]);
if (empty($row)) {
throw new SomeCustomException("No product could be found with id $id");
}
// Create and hydrate the product
$product = $this->hydrate(new Product, $row->current())
$this->loaded[$id] = $product;
return $product;
}
public function save(array $data);
public function update($data);
public function delete($id);
}