2014-10-30 2 views
0

내 응용 프로그램에 적합한 데이터 모델을 작성하는 데 어려움이 있습니다. 데이터의 예로 사람들을 생각해 봅시다. People 클래스와 반대로 Person 클래스의 반복 불가능하지만 재사용 가능한 분리는 어떻게해야합니까? 두 클래스 모두에서 테이블 (및 조인 된 테이블)을 두 번 정의해야한다는 것은 완전히 잘못된 것입니다.OOP에서 품질 데이터 모델 작성

class Person extends CommonModel { 
    protected static $table = 'people'; 
    protected static $join = array('city' => 'city.id = people.city_id'); 

    public function __construct($id) { 
     // Initialize stuff 
    } 

    public function fetch($id) { 
     // Return person with id $id 
    } 

    public function isVeryTall() { 
     // Return boolean 
    } 
} 

class People extends CommonModel { 
    protected static $table = 'people'; 
    protected static $join = array('city' => 'city.id = people.city_id'); 

    public function __construct($id) { 
     // Initialize stuff 
    } 

    public function fetch() { 
     // Return all persons 
    } 
} 

하지만 하나의 클래스로 가입하는 경우, 그것은 사람들의 목록이 반환 될 때 단 한 사람의 맥락에서 의미를 몇 가지 방법은, 사용할 수 있는지 이해가되지 않습니다 . 예를 들어, isVeryTall() 메서드는 실제로 한 사람을 나타내는 개체에서이 메서드를 호출하는 경우에만 작동합니다. 그러나 fetchPeople() 메서드를 호출 한 경우 반환 된 개체에서 내 isVeryTall() 메서드를 사용할 수 있으며 의미가 없습니다 (실제로는 제대로 작동하지 않을 수도 있음).

class Person extends CommonModel { 

    protected static $table = 'people'; 
    protected static $join = array('city' => 'city.id = people.city_id'); 

    public function __construct($id) { 
     // Return one person 
    } 

    public function fetchPeople() { 
     // Returns all people 
    } 

    public function isVeryTall() { 
     // Return boolean 
    } 
} 

또 다른 질문은 사람들의 개체를 반환하는 사람 목록을 반환하는 메서드를 어떻게 구현합니까? 수동으로 모든 행을 반복 한 다음 객체로 인스턴스화해야합니까?

public function fetchPeople() { 
    $people = $this->fetchAll(); 
    foreach($people as $id => $person) { 
     $people[$id] = new Person($person); 
    } 
    return $people; 
} 

답변

0

도메인 클래스에 구현 특정 지속성 코드 (데이터베이스 항목)를 넣지 않겠습니다. 그들을 따로 보관하십시오. 그런 다음 한 사람에게 필요한 물건을 처리하는 Person 클래스를 가질 수 있습니다. Person 객체의 컬렉션의 경우, 그룹에 필요한 특정 메소드 (지속성과 관련이없는)가 있거나 내장 컬렉션 유형 (배열) 중 하나를 사용할 수있는 경우 새 클래스를 정의 할 수 있습니다.

지속성 (데이터베이스) 코드를 별도로 유지하는 데는 여러 가지 방법이 있습니다. 나는 저장소 패턴을 사용한다. 내 도메인 객체와 내 지속성 전략 (데이터베이스) 사이를 변환하는 데 필요한 메소드로 클래스를 작성합니다. 방법 좋아 : 당신이 일을 끝낼 것입니다 무엇

getPerson(PersonCriteria $pc); 
getPeople(PersonCriteria $pc); 
savePerson(Person $p); 
deletePerson($personID); 
etc()... 
+0

그래서 나는 당신이 관련 지속성 프로되지 않은 특정 방법으로 무슨 뜻인지 모르겠습니다. 당신은 저에게 방법의 예를 들어 주시고, 지속성과 관련없는 방법을 주시겠습니까? 나는 비교적 간단한 것을 염두에 두었습니다. 기본적으로 볼 수있는 권한 (예 : 내 그룹에있는 권한)이있는 사람들의 목록입니다. 이것은 내 그룹에 기반하여 생성자에서 형성 될 조건입니다. 자신의 사용자 그룹. 나는 이것이 당신이 지속성과 관련이 있다고 생각하는지 모르겠습니다. –

+0

원래 예제에서'fetchPeople()'은 영속 코드이고'isVeryTall()'은 그렇지 않습니다. 사용 권한을 위해서, 내 도메인 객체에'hasPermission ($ permissionName)'과'getGroupNumber()'를 가지고있다.그리고 기준 개체 내에서 옵션으로 사용 권한 및 그룹 ID를 사용했습니다. criteria 객체는 당신이 원하는 객체를 당신의 영속 계층과 통신하기 위해 생성됩니다. 내용은 일반적으로 WHERE 절로 바뀌지 만 SQL (도메인에 지속성 구현 특정 코드가 없게하기 위해)이 아니라 도메인 언어로 작성됩니다. 희망이 도움이됩니다. –

0


는 당신이 필요로하는 조각의 많은에 대한 바퀴를 다시 만드는 것입니다. 마지막 질문을 해결하는 협회 및 컬렉션에서 물었다. 연관과 컬렉션에서 데이터베이스 쿼리를 구성해야합니다. 당신은 당신의 목표가 아닌 표준 라이브러리의 일부분을 만들 것입니다. 나는 배 라이브러리를 통해 표준 ORM을 보거나 https://github.com/gabordemooij/redbean을 살펴볼 것입니다. 다른 것은 교리와 추진력입니다.

자신의 롤을 만들고 싶다면 첫 번째 방법을 계속 수행하고 섹션 클래스를 사용하여 더 큰 일괄 처리에 대한 페이지 매김 및 쿼리를 수행하는 콜렉션 클래스를 설정하십시오.



    // in a base db class 
    // filters would be pagination and pairs to be used in where clause filtering 
    public function fetch($filters){ 
     return $this->query($filters) 
    } 

    // ... in your child class .. using the existing join and table properties .. I would recommend moving 
    // the associations out into another class but as you can see the details of this can go on and on 
    public function fetchPeople($limit = 10, $page = 1) { 
     $associations = {'table'=> $this->table, 'join'=>$this->join} 
      $people = $this->db->fetch(array('limit'=>$limit,'page'=>$page,$associations); 
     foreach($people as $id => $person) { 
      $people[$id] = new Person($person); 
     } 
     return $people; 
    }