Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP数据映射器-将多个域对象映射到一起_Php_Oop_Design Patterns_Datamapper - Fatal编程技术网

PHP数据映射器-将多个域对象映射到一起

PHP数据映射器-将多个域对象映射到一起,php,oop,design-patterns,datamapper,Php,Oop,Design Patterns,Datamapper,我正在开发一个页面,用户可以在其中查看图形图像的概述,这些图像表示进出网络设备端口的Internet流量。有关这些端口的信息收集在一个表中。此表中每个端口至少包含以下列: 端口ID 设备ID 端口名 还有更多 设备ID列是另一个表的主键:设备。此表至少包含以下列: 设备ID 设备名称 还有更多 如您所见,这两个表之间存在设备ID的关系。我已将这两个表转换为域对象“Port”和“Device”。两个域对象都由两个域映射器“PortMapper”和“DeviceMapper”填充。每个端口需

我正在开发一个页面,用户可以在其中查看图形图像的概述,这些图像表示进出网络设备端口的Internet流量。有关这些端口的信息收集在一个表中。此表中每个端口至少包含以下列:

  • 端口ID
  • 设备ID
  • 端口名
  • 还有更多
设备ID列是另一个表的主键:设备。此表至少包含以下列:

  • 设备ID
  • 设备名称
  • 还有更多
如您所见,这两个表之间存在设备ID的关系。我已将这两个表转换为域对象“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;
}
以及我的设备apper的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();
}
我可以很好地获得每个端口的设备主机名。但是我例举整个事情的方式真的很糟糕。如何更好地处理两个域对象之间的关系


我可以做一个简单的左连接查询,这样我就不需要将两个域对象映射到一起,但这不是我想去的地方。

我想你需要重新构造一些东西。首先,我建议您的数据映射器填充域对象。毕竟,这就是他们应该做的:将数据映射到对象上。此方法允许您在域对象上设置已知属性,然后调用数据映射器“获取”给定已知变量的其余数据

我建议的下一件事是创建域对象集合类。这些实体集合本质上是美化的数组,如果实现正确,它们可以起到类似的作用。这些更改将有助于生成您想要更好地映射的关系(请参见下面的代码)。此外,有了这个建议,您的映射器将承担一个更为单一的责任,如果您愿意,将其他关系逻辑排除在映射器之外/助手类中

下面我将说明我将如何着手构建这项任务。首先,创建PortCollection并设置ID上的条件。然后,我们可以在PortCollectionMapper上映射PortCollection。在进行必要的数据库调用之后,PortCollectionMapper将结果发送到PortCollection,后者为获取的每一行实例化新的端口实例,并将其添加到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 );
}

为什么不使用像这样的ORM框架呢?通过编写我自己的代码,我学到的不仅仅是使用像Doctrine这样的大型ORM框架。足够好了。然后按照Doctrine或其他框架使用的模式自己实现功能。我将看一看Doctrine ORM。我认为提到
fetch
使用的是按引用传递是很有用的。剩下的例子很好,谢谢你的例子。我曾考虑过使用收藏,但由于某种原因,我无法理解它。在编写这样的代码时,我应该始终牢记单一责任原则。这将是一个关于处理集合的好教程吗?@Jeremy我也用过你的。非常有帮助!是否也可以将$portCollection传递给$portCollectionMapper的构造函数,而不是传递给fetch()?