2016-06-09 6 views
2

네트워크 장치의 포트에서 들어오고 나가는 인터넷 트래픽을 나타내는 그래픽 이미지 개요를 볼 수있는 페이지를 개발 중입니다. 이러한 포트에 대한 정보는 테이블에 수집됩니다. 이 표가 적어도 포트 당 다음과 같은 열 :PHP 데이터 매퍼 - 여러 도메인 객체를 함께 매핑

  • 포트 ID
  • 장치 ID
  • 포트 이름
  • 더 ...

장치 ID 열이 기본 키 다른 테이블 : 장치. 이 테이블은 적어도 다음과 같은 열이

  • 장치 ID
  • 장치 이름
  • 더 ...

당신이 볼 수 있듯이, 장치에 의해이 두 테이블 사이의 관계가 신분증. Domain Objects 'Port'와 'Device'에이 두 테이블을 번역했습니다. 두 도메인 객체는 두 개의 도메인 맵퍼 'PortMapper'와 'DeviceMapper'에 의해 채워집니다. 모든 포트에서 필요한 속성 중 하나는 장치 ID를 통해 얻을 수있는 DeviceName입니다. 내 질문은이 두 도메인 개체를 가장 잘 매핑 할 수있는 방법에 관한 것입니다.

내 매퍼의 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 쿼리를 수행 할 수 있습니다.하지만이 위치는 내가 원하는 곳이 아닙니다.

+0

왜 [교리 ORM]와 같은 ORM 프레임 워크를 사용하지 않는 (http://www.doctrine-project.org/projects/orm.html)? –

+1

내 자신의 코드를 작성함으로써 Doctrine과 같은 큰 ORM 프레임 워크를 사용하는 것 이상을 배웁니다. – Beeelze

+0

충분합니다. 그런 다음 Doctrine 또는 다른 프레임 워크 패턴을 따르고 직접 기능을 사용하고 구현하십시오. –

답변

1

몇 가지 사항을 재구성해야한다고 생각합니다. 우선, 데이터 맵퍼가 도메인 객체를 채우는 것이 좋습니다. 결국 데이터가 객체에 매핑됩니다. 이 방법을 사용하면 도메인 객체에 알려진 속성을 설정 한 다음 알려진 변수를 사용하여 나머지 데이터를 "가져 오기"위해 데이터 매퍼를 호출 할 수 있습니다.

다음으로 제안 할 것은 도메인 객체 컬렉션 클래스를 만드는 것입니다. 이러한 엔티티 컬렉션은 본질적으로 영광스러운 배열이며 정확하게 구현되면 역할을 할 수 있습니다. 이러한 변화는 당신이 더 잘 맵핑하고자하는 관계를 만드는 데 도움이 될 것입니다 (아래 코드 참조). 또한이 조언을 사용하면 맵퍼가보다 단순한 책임을 맡고 다른 관계형 논리를 매퍼에서/헬퍼 클래스에서 벗어나도록 선택할 수 있습니다.

다음은이 작업을 구조화하는 방법을 보여줍니다. 먼저 PortCollection이 만들어지고 ID의 조건이 설정됩니다. 그런 다음 PortCollectionMapper에 PortCollection을 매핑 할 수 있습니다.필요한 데이터베이스 호출을 한 후에 PortCollectionMapper는 결과를 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); 
} 
+0

'fetch'가 참조에 의한 패스를 사용하고 있다고 언급하는 것이 유용하다고 생각합니다. 나머지 좋은 예를 들어. – dbf

+0

이 예를 들어 주셔서 감사합니다. 나는 콜렉션을 사용하는 것에 대해 생각해 왔지만 어떤 이유로 든 콜렉션을 둘러 볼 수는 없었다. 이와 같은 코드를 작성할 때는 항상 Single Responsibility Principle을 염두에 두어야합니다. – Beeelze

+0

[this] (https://www.sitepoint.com/handling-collections-of-aggregate-roots/) 컬렉션 처리에 관한 훌륭한 자습서가 될 수 있습니까? – Beeelze