2011-04-21 4 views
2

내가 작업하고있는 애플리케이션에 대해 doctrine을 사용하고 있습니다. 그러나 문서를 읽은 후에 엔티티 측면에서 데이터베이스 구조를 나타내는 방법을 개념화하는 데 문제가 있습니다. .두 테이블을 Doctrine2의 한 엔티티에 매핑하기

내가 좋아하는 번역 데이터를 보유 파트너 테이블이 여러 테이블이 다음과 같은 .... 나는에 대한 액세스 권한을 가지고 하나의 엔티티 (탐색 요소)하고 싶은

Tables ER diagram

' 내 응용 프로그램에서 설정 한 언어에 따라 'label'필드가 필요합니다. 다음은 교리 문서에서 다음

http://www.doctrine-project.org/docs/orm/2.0/en/reference/basic-mapping.html 기본적으로 기업은 이 같은 와 함께 테이블에 지속 될 것입니다 당신이 개체를 유지하는 데 사용됩니다 하나 (하나의) 테이블을 정의 할 필요가 있음을 시사하는 것 name을 클래스 이름으로 사용하십시오.

을 아니면이 두 가지 요소를 정의하고 연결 (또는 변환 표는 요소 테이블에서 상속 할 수 있도록)해야합니까 다음과 같이 당신이 @Table 주석을 사용할 수 변경하기 위해.

그리고 어떤 전략을 사용하여 Join에 language_id 절을 삽입하면 (현재 설정된 언어의 올바른 레이블을 가져 오도록 할 수 있습니다). 이것은 엔티티 자체 또는 다른 곳에서 정의 할 수 있습니까?

답변

2

이것은 One-To-Many Bidirectional association에 적합합니다.

public function getLabel($languageId) { 

    foreach($this->translations as $trans) { 
     if($trans->languageId == $languageId) 
      return $trans->label; 
    } 

    throw new InvalidArgumentException(); 
} 

그리고 당신은 할 수 :

/** @Entity */ 
class NavigationElement 
{ 
    // ... 
    /** 
    * @OneToMany(targetEntity="NavigationElementTranslation", mappedBy="navigationElement") 
    */ 
    private $translations; 
    // ... 

    public function __construct() { 
     $this->translations = new \Doctrine\Common\Collections\ArrayCollection(); 
    } 
} 

/** @Entity */ 
class NavigationElementTranslation 
{ 
    // ... 
    /** 
    * @ManyToOne(targetEntity="NavigationElement", inversedBy="translations") 
    * @JoinColumn(name="navigation_element_id", referencedColumnName="id") 
    */ 
    private $navigationElement; 
    // ... 
} 

당신은 올바른 레이블을 얻을 수있는 번역을 통해 검색하는 NavigationElement 엔티티에 getLabel($languageId) 방법을 추가 할 수 있습니다 :이 상황에 번역 해당 페이지에서 시나리오

$query = $em->createQuery(
    "SELECT ne, net 
    FROM Entity\NavigationElement ne 
    JOIN ne.translations net WITH net.languageId = :langId" 
); 
$query->setParameter('langId', $languageId); 
$navigationElements = $query->execute(); 

목 : 당신은 단지 $translations 특성에 원하는 번역을로드하기 위해 다음과 같은 DQL을 사용 공격적으로 캐시하려는 상황과 비슷합니다. 당신도 Doctrine 2's caching 메커니즘을 조사해야합니다.

또한 번역을위한 조인 테이블이 관리하기 시작하기 시작하면 gettext으로 PHP에서 국제화를 적절하게 처리 할 수 ​​있습니다.

+0

정말 큰 설명에 감사드립니다. 내 도메인 내에서 (자체적으로) 의미가없는 엔티티 (번역)를 만들 필요성을 이해하는 데 문제가 있다고 생각합니다. 물론 제공 한 예를 들어서 직접 액세스하지 않아도되지만, 오히려 투명하게 요소 자체를 통해. – calumbrodie

+0

로조카의 대답은 꽤 좋지만, 그의 마지막 문장 또한 큰 힌트입니다. 귀하의 직감은 정확합니다. 국제화 (I18N)는 까다 롭습니다. 도메인에서 그 물건을 추상화하는 것이 더 좋습니다.gettext는 매우 유용 할 수 있으며 다른 메커니즘이 있습니다. ZF의 Zend_Locale과 Zend_Translate는 예를 들어 프레임 워크와는 별도로 유용하게 사용할 수 있습니다. 이것이 큰 프로젝트이고 많은 번역 작업이 필요하다면 (그리고 시간이 있다면) 큰 걸음을 내딛고 i18n에 대한 연구를 시작하십시오. – timdev

+0

@timdev 의견을 주셔서 감사합니다. 프로젝트의 범위는 현재 시스템이 작동중인 방식을 모델링하는 것입니다. 고맙게도 그것은 매우 정교하지 않아서 내 솔루션이 필요하지 않습니다 (이미없는 기능을 추가하려고하지는 않습니다) 그리고 맞습니다 -이 특정한 경우에도 i18n에 대한 나의 이해는 매우 제한적입니다 나는 (몇개의) 도메인 객체의 이름에 대한 간단한 번역만을 다룰 필요가있다. 필자가 언급 한 패키지와 symfony의 현지화 및 국제화 기능을 살펴 보겠습니다. – calumbrodie

0

다음 교리 확장을 살펴보기 위해이 동일한 문제를 해결해야하는 사람에게도 도움이 될 것입니다.

http://www.gediminasm.org/article/translatable-behavior-extension-for-doctrine-2

+3

위의 걸린 사람에게만 메모 : 위의 확장은 EAV를 사용하여 데이터를 저장하므로 작은 데이터 세트 이외의 다른 것에는 대단히 비효율적입니다. 번역이 필요한 엔티티가 많고 실적에 관심이 있다면 자신 만의 롤을 만들어야합니다. – calumbrodie

+0

EAV를 사용하기 때문에 정말로 "매우 비효율적 인"것으로 분류 할 수 있습니까? 나는 전문가는 아니지만 어쩌면 이것은 성능 문제를 해결할 것이다 http://www.gediminasm.org/article/translatable-behavior-extension-for-doctrine-2#orm-query-hint – ZolaKt

+0

@calumbrodie 그 링크 오프라인 상태입니다 (404). 확인 됨 2016-06-08 – feeela

관련 문제