ZF2 + Doctrine:通过TableGateway从数据库中读取数据,并将Doctrine实体及其相关对象包含在其中

时间:2016-09-22 14:16:38

标签: php doctrine-orm zend-framework2

我正在为我们的传统网店开发集中管理软件。这些商店是由第三方开发的,并且相当陈旧,所以他们也使用相当古老的做法。订单及其相关对象存储在一个表中,因此该表具有很多字段并且非常臃肿。我们的新管理系统采用关系方法。 I. e。我有一个用于存储订单的表order和一个用于存储所有地址的表address。每个order都通过外键引用其送货地址和帐单邮寄地址。 Doctrine 2用于处理这些实体及其关系。

显然,我必须将商店的订单导入我们管理系统的数据库。这通过直接访问每个商店的数据库,查询订单数据并将其插入管理系统自己的数据库中来实现。

我正在使用ZF2 TableGateway来检索商店中的数据,我想使用Doctrine的DoctrineObject水合剂来尽可能少地处理我的实体。但是,DoctrineObject水合器开箱即用,期望相关对象在嵌套数组中传递。因为我还没有想出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']
    // ...
}

因此,为了避免手动处理,我可以想到两种可能的解决方案:

  1. 找到一种方法使TableGatway返回多维结果
  2. 找到一种方法使DoctrineHydrator能够通过前缀数组元素而不是嵌套数组填充相关对象
  3. 我们几年前一直在使用Propel2,如果我没记错的话,Propel的保温器可以通过前缀自动填充单维数组中的相关对象,这与我手动处理接收数据的方式非常相似。就我所见,Doctrine保湿器不能做到这一点,尽管我猜你可以用策略来实现这个目标。

    在深入研究策略或派生的TableGateway之前,有人知道开箱即用的解决方案吗?或者我目前的方法是最好的?

1 个答案:

答案 0 :(得分:1)

我认为您当前将数据映射到水合器所期望的格式的过程会更好,因为您使用了命名策略(因为您有一个平面阵列而水合器需要嵌套的)。

您甚至可以创建一个复合水合器来封装映射。

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);
    }
}