Retrieving every field of a database row as object

2019-08-03 11:36发布

问题:

I know we have result set to get a row as object But How can I get every field as a separate object ? consider of this database row :

user_id     address_id  product_id  shop_id
5               3       134          2

I want to retrieve and save the row as follows :

userEntity  AddressEntity   ProductEntity   ShopEntity

回答1:

This is not how the TableDataGateway is supposed to be used, since what you are looking for are more complex features such as the ones of Doctrine 2 ORM and similar data-mappers.

Here is one possible solution to the problem, which involves using a custom hydrator (docs). My example is simplified, but I hope it clarifies how you are supposed to build your resultset.

First, define your entities (I'm simplifying the example assuming that UserEntity is the root of your hydration):

class UserEntity {
    /* fields public for simplicity of the example */
    public $address;
    public $product;
    public $shop;
}
class AddressEntity { /* add public fields here for simplicity */ }
class ProductEntity { /* add public fields here for simplicity */ }
class ShopEntity { /* add public fields here for simplicity */ }

Then, build hydrators specific for the single entities:

use Zend\Stdlib\Hydrator\HydratorInterface as Hydrator;

class AddressHydrator implements Hydrator {
    // @TODO: implementation up to you
}

class ProductHydrator implements Hydrator {
    // @TODO: implementation up to you
}

class ShopHydrator implements Hydrator {
    // @TODO: implementation up to you
}

Then we aggregate these hydrators into one that is specifically built to hydrate a UserEntity:

class UserHydrator extends \Zend\Stdlib\Hydrator\ObjectProperty {
    public function __construct(
        Hydrator $addressHydrator,
        Hydrator $productHydrator,
        Hydrator $shopHydrator
    ) {
        $this->addressHydrator = $addressHydrator;
        $this->productHydrator = $productHydrator;
        $this->shopHydrator    = $shopHydrator;
    }

    public function hydrate(array $data, $object)
    {
        if (isset($data['address_id'])) {
            $data['address'] = $this->addressHydrator->hydrate($data, new AddressEntity());
        }

        if (isset($data['product_id'])) {
            $data['product'] = $this->productHydrator->hydrate($data, new ProductEntity());
        }

        if (isset($data['shop_id'])) {
            $data['shop'] = $this->shopHydrator->hydrate($data, new ShopEntity());
        }

        return parent::hydrate($data, $object);
    }
}

Now you can use it to work with your resultset. Let's define the service for your UserEntityTableGateway:

 'UserEntityTableGateway' => function ($sm) {
     $dbAdapter          = $sm->get('Zend\Db\Adapter\Adapter');
     $resultSetPrototype = new ResultSet();

     $resultSetPrototype->setArrayObjectPrototype(new UserHydrator());

     return new TableGateway('user', $dbAdapter, null, $resultSetPrototype);
 },

These are all simplified examples, but they should help you understanding how powerful hydrators can be, and how you can compose them to solve complex problems.

You may also check the chapters in the documentation about the Aggregate Hydrator and Hydration Strategies, which were designed specifically to solve your problem.