PHP 数据映射器 - 将多个域对象映射在一起
PHP Data mapper - map multiple domain objects together
我正在开发一个页面,用户可以在其中查看表示进出网络设备端口的 Internet 流量的图形图像的概览。有关这些端口的信息收集在 table 中。 table 每个端口至少有以下列:
- 端口号
- 设备 ID
- 端口名称
- 还有更多...
设备 ID 列是另一个 table 的主键:设备。这个table至少有以下列:
- 设备 ID
- 设备名称
- 还有更多...
如您所见,这两个 table 之间存在按设备 ID 的关系。我已将 table 都翻译成域对象 'Port' 和 'Device'。两个域对象都由两个域映射器 'PortMapper' 和 'DeviceMapper' 填充。我需要从每个端口获取的一个属性是 DeviceName,我可以通过设备 ID 获取它。我的问题是关于如何最好地将这两个域对象映射在一起。
我的 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 的 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();
}
我很好地获得了每个端口的设备主机名。但是我实例化整个事情的方式真的很糟糕。什么是处理两个域对象之间关系的更好方法?
我可以做一个简单的 LEFT JOIN 查询,这样我就不需要将两个域对象映射在一起,但这不是我想去的地方。
我认为您需要重组一些内容。首先,我建议您的数据映射器填充您的域对象。毕竟,这就是他们应该做的:将数据映射到对象上。此方法允许您在域对象上设置已知属性,然后调用数据映射器以 "fetch" 给定已知变量的其余数据。
我建议的下一件事是创建域对象集合 classes。这些实体集合本质上是经过美化的数组,如果实施得当,它们可以起到同样的作用。这些更改将有助于生成您想要更好地映射的关系(请参见下面的代码)。此外,有了这个建议,您的映射器将承担更单一的责任,将其他关系逻辑留在 mapper/in 助手 class 之外,如果您愿意的话。
下面我将说明我将如何构建此任务。首先,创建一个 PortCollection 并设置 ID 的条件。然后我们可以将 PortCollection 映射到 PortCollectionMapper 上。在进行必要的数据库调用后,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 );
}
我正在开发一个页面,用户可以在其中查看表示进出网络设备端口的 Internet 流量的图形图像的概览。有关这些端口的信息收集在 table 中。 table 每个端口至少有以下列:
- 端口号
- 设备 ID
- 端口名称
- 还有更多...
设备 ID 列是另一个 table 的主键:设备。这个table至少有以下列:
- 设备 ID
- 设备名称
- 还有更多...
如您所见,这两个 table 之间存在按设备 ID 的关系。我已将 table 都翻译成域对象 'Port' 和 'Device'。两个域对象都由两个域映射器 'PortMapper' 和 'DeviceMapper' 填充。我需要从每个端口获取的一个属性是 DeviceName,我可以通过设备 ID 获取它。我的问题是关于如何最好地将这两个域对象映射在一起。
我的 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 的 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();
}
我很好地获得了每个端口的设备主机名。但是我实例化整个事情的方式真的很糟糕。什么是处理两个域对象之间关系的更好方法?
我可以做一个简单的 LEFT JOIN 查询,这样我就不需要将两个域对象映射在一起,但这不是我想去的地方。
我认为您需要重组一些内容。首先,我建议您的数据映射器填充您的域对象。毕竟,这就是他们应该做的:将数据映射到对象上。此方法允许您在域对象上设置已知属性,然后调用数据映射器以 "fetch" 给定已知变量的其余数据。
我建议的下一件事是创建域对象集合 classes。这些实体集合本质上是经过美化的数组,如果实施得当,它们可以起到同样的作用。这些更改将有助于生成您想要更好地映射的关系(请参见下面的代码)。此外,有了这个建议,您的映射器将承担更单一的责任,将其他关系逻辑留在 mapper/in 助手 class 之外,如果您愿意的话。
下面我将说明我将如何构建此任务。首先,创建一个 PortCollection 并设置 ID 的条件。然后我们可以将 PortCollection 映射到 PortCollectionMapper 上。在进行必要的数据库调用后,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 );
}