我正在开发一个页面,用户可以在其中查看图形图像的概述,这些图像代表进出网络设备端口的互联网流量。有关这些端口的信息收集在表格中。此表每个端口至少包含以下列:
“设备ID”列是另一个表的主键:设备。该表至少包含以下列:
如您所见,这两个表之间存在Device ID关系。我已将这两个表格翻译成Domain Objects' Port'和'设备'。两个域对象都填充了两个域对象' PortMapper'和' DeviceMapper'。我需要每个端口的一个属性是DeviceName,我可以通过设备ID获取。我的问题是如何最好地将这两个Domain对象映射到一起。
我的PortMapper findById()功能如下所示:
public function findById($id, DeviceMapper $deviceMapper) {
$ports = $this->db->sql_select('SELECT * FROM ports WHERE customer_id = ?', [$id]);
$arrayOfPorts = [];
foreach($ports as $port) {
$device = $deviceMapper->findById($port['device_id']);
$port['device'] = $device;
$arrayOfPorts[] = $this->createObject($port);
}
return $arrayOfPorts;
}
我的DeviceMapper< strong> findById()功能:
public function findById($id) {
$device = $this->db->sql_select('SELECT * FROM devices WHERE device_id = ?', [$id]);
return $this->createObject($device);
}
我实例化它的方式是在我的控制器中:
$db = new Database('librenms');
$portMapper = new PortMapper($db);
$deviceMapper = new DeviceMapper($db);
$ports = $portMapper->findById($_SESSION['user']['id'], $deviceMapper);
foreach($ports as $port) {
echo $port->getHostname();
}
我为每个端口获取Device的主机名就好了。但是我实例化整个事情的方式非常糟糕。什么是更好的方法来处理两个域对象之间的关系?
我可以做一个简单的LEFT JOIN查询,这样我就不需要将两个域对象映射到一起了,但那不是我想去的地方。
答案 0 :(得分:1)
我认为你需要重组一些事情。首先,我建议您的数据映射器填充您的域对象。毕竟,这就是他们应该做的事情:将数据映射到对象上。此方法允许您在域对象上设置已知属性,然后在给定已知变量的情况下调用数据映射器以“获取”其余数据。
我建议的下一件事是创建域对象集合类。这些实体集合本质上是美化的数组,如果正确实现,可以这样做。这些更改将有助于更好地生成您想要映射的关系(请参阅下面的代码)。此外,有了这个建议,你的映射器将承担更多的单一责任,如果您愿意,将其他关系逻辑留在映射器/辅助类中。
下面我将说明如何构建此任务。首先,创建一个PortCollection并设置ID的条件。然后我们可以在PortCollectionMapper上映射PortCollection。在进行必要的数据库调用之后,PortCollectionMapper将结果发送到PortCollection,PortCollection为获取的每一行实例化新的Port实例,并将其添加到PortCollection。
现在,我们可以遍历PortCollection并使用DeviceMapper来填充有关设备的信息。
<?php
$portCollection = new PortCollection;
$portCollection->setId( $_SESSION['user']['id'] );
$portCollectionMapper = new PortCollectionMapper;
$portCollectionMapper->fetch( $portCollection );
//$portCollection is now populated with Port instances
$deviceMapper = new DeviceMapper;
foreach( $portCollection as $port )
{
//create a device from the port device ID
$device = new Device;
$device->setId( $port->getDeviceId() );
//populate the device with data
$deviceMapper->fetch( $device );
//assign the device to the port
$port->setDevice( $device );
}