I am developing a centralized management software for our legacy web shops. These shops have been developed by a third party and are quite old, so they use pretty old practices too. Orders and their related objects are stored in one single table, therefore this table has a lot of fields and is quite bloated. Our new management system uses a relational approach. I. e. I have a table order
to store the orders and a table address
to store all addresses. Each order
references its shipping and billing address via foreign keys. Doctrine 2 is used for handling these entities and their relations.
Obviously I have to import the orders from the shops into the database of our management system. This happens by directly accessing the database of each shop, querying the order data and inserting it in the management system's own database.
I am using the ZF2 TableGateway
to retrieve the data from the shops and I would like to hydrate my entities using Doctrine's DoctrineObject
hydrator with as little processing as possible. However, out of the box the DoctrineObject
hydrator expects related objects to be passed in nested arrays. Because I have not yet figured out if the TableGateway
can produce a multi dimensional result, I have to process the received data manually before passing it to the hydrator.
// $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']
// ...
}
So, to avoid the manual processing, I can think of two possible solutions:
- find a way to make the
TableGatway
return multi dimensional results - find a way to make the
DoctrineHydrator
able to populate related objects by prefixed array elements instead of nested arrays
We have been using Propel2 a couple of years ago and if I remember correctly, Propel's hydrator could automatically populate related objects from a single dimensional array via prefixes, quite similar to how I manually process the received data. The Doctrine hydrator can't do that as far as I could see, though I guess you could use strategies to accomplish this.
Before I dive deep into developing strategies or a derived TableGateway
, does somebody know an out-of-the-box solution? Or is my current approach the best it can get?