Suppose I have a query that returns the following data:
RangeId | MinValue | MaxValue | Resolution | UnitId | UnitName
I want to hydrate the object MeasurementRange
with the above data.
class MeasurementRange {
public function getRangeId() {...};
public function setRangeId($id) {...};
public function getRange() {...};
public function setRange(Range $range) {...};
public function getUnit() {...};
public function setUnit(Unit $unit) {...};
}
class Range {
public function getMinValue() {...};
public function setMinValue(float $minVal) {...};
public function getMaxValue() {...};
public function setMaxValue(float $maxVal) {...};
public function getResolution {...};
public function setResolution(float $resolution) {...};
}
class Unit {
public function getUnitId() {...};
public function setUnitId(int $id) {...};
public function getUnitName() {...};
public function setUnitName(string $name) {...};
}
As you can see the MeasurementRange
object has set Range
and Unit
objects.
How can I hydrate MeasurementRange
and the inner Range
and Unit
objects from the above query?
PS: I didn't specify protected properties of the objects. I guess they are self-evident.
You need to create a mapper, that will use your dbAdapter to fetch the data as an array, and then use hydrators to hydrate all the objects, and finally add the Range
and Unit
to MeasurementRange
. You could alternatively create a custom hydrator (that would be even better, in terms of single responsibility).
I haven't got time to clean the example below, but that's what it could look like :)
final class LanguageMapper
{
/**
* @param LanguageTable $languageTable
* @param PackageTable $packageTable
* @param Cache $cache
* @param LoggerInterface $logger
*/
public function __construct(LanguageTable $languageTable, PackageTable $packageTable, Cache $cache, LoggerInterface $logger)
{
$this->languageTable = $languageTable;
$this->packageTable = $packageTable;
$this->cache = $cache;
$this->logger = $logger;
}
/**
* @param array $where
*
* @return array List of active languages
*/
public function findActive(array $where = [])
{
try {
if (empty($where) && $this->cache->hasItem('active_languages')) {
return unserialize($this->cache->getItem('active_languages'));
}
} catch (RuntimeException $exception) {
$this->logger->critical($exception->getMessage(), [
'exception' => $exception,
'file' => $exception->getFile(),
'line' => $exception->getLine(),
]);
}
/* @var $adapter \Zend\Db\Adapter\Adapter */
$adapter = $this->languageTable->getGateway()->getAdapter();
$sql = new Sql($adapter);
$select = $sql->select()->columns([Select::SQL_STAR])
->from('language')
->join('package', 'package.id = language.package', Select::SQL_STAR, Select::JOIN_LEFT)
->where(array_merge($where, ['active' => true]))
->order(['position']);
$selectString = $sql->buildSqlString($select);
$resultSet = $adapter->query($selectString, Adapter::QUERY_MODE_EXECUTE);
$languages = [];
$hydrator = new ArraySerializable();
foreach ($resultSet as $result) {
$language = new Language();
$package = new Package();
$hydrator->hydrate((array) $result, $package);
$hydrator->hydrate((array) $result, $language);
$language->setPackage($package);
$languages[] = $language;
}
if (empty($where)) {
try {
$this->cache->setItem('active_languages', serialize($languages));
} catch (RuntimeException $exception) {
$this->logger->warning($exception->getMessage(), [
'exception' => $exception,
'file' => $exception->getFile(),
'line' => $exception->getLine(),
]);
}
}
return $languages;
}
}