ZF2 + Doctrine:通过 TableGateway 从数据库中读取数据并将 Doctrine 实体及其相关对象与它混合
ZF2 + Doctrine: Read data from a database via TableGateway and hydrate Doctrine entity including its related objects with it
我正在为我们的遗留网上商店开发一个集中管理软件。这些商店都是第三方开发的,比较老,所以也都是比较老的做法。订单及其相关对象存储在一个单一的 table 中,因此这个 table 有很多字段并且非常臃肿。我们的新管理系统使用关系方法。 IE。我有一个 table order
来存储订单和一个 table address
来存储所有地址。每个 order
通过外键引用其送货和账单地址。 Doctrine 2 用于处理这些实体及其关系。
显然我必须将商店的订单导入到我们管理系统的数据库中。这是通过直接访问每个商店的数据库,查询订单数据并将其插入管理系统自己的数据库来实现的。
我正在使用 ZF2 TableGateway
从商店检索数据,我想使用 Doctrine 的 DoctrineObject
水合器来水合我的实体,并尽可能少地进行处理。但是,开箱即用的 DoctrineObject
hydrator 期望相关对象在嵌套数组中传递。因为我还没有弄清楚TableGateway
是否可以产生多维结果,所以我必须在将接收到的数据传递给水化器之前手动处理它。
// $shop_db is a configured \Zend\Db\Adapter\Adapter to
// access the shop's database
$orders_table = new TableGateway(['order' => 'shop_orders'], $shop_db);
$order_data = $orders_table
->select(
function(Select $select) {
$select->columns([
// Note: I am renaming the source fields to
// their internal equivalent via aliases
'source_order_id' => 'id',
'remarks' => 'customer_remarks',
'created_at' => 'order_date',
// Prefix the shipping address data with
// "shipping_address_" so we can easily
// extract it later
'shipping_address_firstname' => 'safirst',
'shipping_address_lastname' => 'salast',
'shipping_address_company' => 'sacomp',
'shipping_address_street' => 'sastreet',
'shipping_address_zip_code' => 'sazip',
'shipping_address_city' => 'sacity'
]);
$select->order('id');
}
);
// Process each order so its data can be
// digested by the DoctrineObject hydrator
foreach($order_data as $order)
{
// ...
// extract each element that has the
// prefix "shipping_address_" from the $order
// and copy it to a nested array $order['shipping_address']
// ...
}
所以,为了避免手动处理,我想到了两种可能的解决方案:
- 想办法制作
TableGatway
return 多维结果
- 找到一种方法使
DoctrineHydrator
能够通过带前缀的数组元素而不是嵌套数组来填充相关对象
几年前我们一直在使用 Propel2,如果我没记错的话,Propel 的水化器可以通过前缀自动填充一维数组中的相关对象,这与我手动处理接收到的数据的方式非常相似。据我所知,Doctrine 水化器无法做到这一点,但我猜你可以使用策略来实现这一点。
在我深入研究制定策略或派生 TableGateway
之前,有人知道开箱即用的解决方案吗?还是我目前的方法是最好的?
我认为你当前将数据映射到你的水化器期望的格式的过程比使用命名策略更好(因为你有一个平面数组并且水化器需要一个嵌套的)。
您甚至可以创建复合水化器来封装映射。
class MyHydrator implements HydratorInterface
{
// The class that does the data conversion
protected $mapper;
// The doctrine hydrator
protected $hydrator;
public function hydrate($data, $object)
{
// Return the data to the format that is expected
$data = $this->mapper->map($data);
return $this->hydrator->hydrate($data, $object);
}
public function extract($object)
{
$data = $this->hydrator->extract($object);
// Reverse the data into a flat structure
return $this->mapper->unmap($data);
}
}
我正在为我们的遗留网上商店开发一个集中管理软件。这些商店都是第三方开发的,比较老,所以也都是比较老的做法。订单及其相关对象存储在一个单一的 table 中,因此这个 table 有很多字段并且非常臃肿。我们的新管理系统使用关系方法。 IE。我有一个 table order
来存储订单和一个 table address
来存储所有地址。每个 order
通过外键引用其送货和账单地址。 Doctrine 2 用于处理这些实体及其关系。
显然我必须将商店的订单导入到我们管理系统的数据库中。这是通过直接访问每个商店的数据库,查询订单数据并将其插入管理系统自己的数据库来实现的。
我正在使用 ZF2 TableGateway
从商店检索数据,我想使用 Doctrine 的 DoctrineObject
水合器来水合我的实体,并尽可能少地进行处理。但是,开箱即用的 DoctrineObject
hydrator 期望相关对象在嵌套数组中传递。因为我还没有弄清楚TableGateway
是否可以产生多维结果,所以我必须在将接收到的数据传递给水化器之前手动处理它。
// $shop_db is a configured \Zend\Db\Adapter\Adapter to
// access the shop's database
$orders_table = new TableGateway(['order' => 'shop_orders'], $shop_db);
$order_data = $orders_table
->select(
function(Select $select) {
$select->columns([
// Note: I am renaming the source fields to
// their internal equivalent via aliases
'source_order_id' => 'id',
'remarks' => 'customer_remarks',
'created_at' => 'order_date',
// Prefix the shipping address data with
// "shipping_address_" so we can easily
// extract it later
'shipping_address_firstname' => 'safirst',
'shipping_address_lastname' => 'salast',
'shipping_address_company' => 'sacomp',
'shipping_address_street' => 'sastreet',
'shipping_address_zip_code' => 'sazip',
'shipping_address_city' => 'sacity'
]);
$select->order('id');
}
);
// Process each order so its data can be
// digested by the DoctrineObject hydrator
foreach($order_data as $order)
{
// ...
// extract each element that has the
// prefix "shipping_address_" from the $order
// and copy it to a nested array $order['shipping_address']
// ...
}
所以,为了避免手动处理,我想到了两种可能的解决方案:
- 想办法制作
TableGatway
return 多维结果 - 找到一种方法使
DoctrineHydrator
能够通过带前缀的数组元素而不是嵌套数组来填充相关对象
几年前我们一直在使用 Propel2,如果我没记错的话,Propel 的水化器可以通过前缀自动填充一维数组中的相关对象,这与我手动处理接收到的数据的方式非常相似。据我所知,Doctrine 水化器无法做到这一点,但我猜你可以使用策略来实现这一点。
在我深入研究制定策略或派生 TableGateway
之前,有人知道开箱即用的解决方案吗?还是我目前的方法是最好的?
我认为你当前将数据映射到你的水化器期望的格式的过程比使用命名策略更好(因为你有一个平面数组并且水化器需要一个嵌套的)。
您甚至可以创建复合水化器来封装映射。
class MyHydrator implements HydratorInterface
{
// The class that does the data conversion
protected $mapper;
// The doctrine hydrator
protected $hydrator;
public function hydrate($data, $object)
{
// Return the data to the format that is expected
$data = $this->mapper->map($data);
return $this->hydrator->hydrate($data, $object);
}
public function extract($object)
{
$data = $this->hydrator->extract($object);
// Reverse the data into a flat structure
return $this->mapper->unmap($data);
}
}