2016-12-22 8 views
1

많은 전자 메일이있는 Person 모델 개념을 만들었습니다. Person (Person 모델)과 동일한 전자 메일을 공유 할 수있는 회사 모델도 있습니다. (조인 테이블을 가진 단방향 manytomany 고전) 사람들 OneToMany PeopleEmail ManyToOne 이메일Symfony/Doctrine 조건 및 제한이있는 ManyToMany

people { id, firstname, lastname, created } 
people_emails { person_id, email_id, main, created } 
emails { id, email, created } 

뿐만 아니라 : 한마디로

companies { id, name, employee_count, created } 
companies_emails { company_id, email_id, main, created } 
emails { id, email, created } 

문제이며, 내가하고 싶은 것을 다음과 같이 "main"이라는 부울 값을 조인 테이블에 저장하십시오.

person_id | email_id | main | created 
    8  |  5 | true | 2014-10-21 16:54:21 

... 나는이 작업을 수행 할 수 있도록 :

Mark Wilson (Person) has 5 emails. 
3 of them are his company e-mails (shared): [email protected], [email protected], [email protected] 
2 of them are his own. 
1 he answers only in his leisure time 
1 is his MAIN email: i.e. [email protected] 

대신 모든 5 이메일을 가져 오는의는 일반 사람이 모델을 열였다 것처럼, 난 쉽게 기본 이메일을 좀하고 싶습니다 :

firstname: Mark (string) 
lastname: Wilson (string) 
emails: (array) 
primary_email: (email object) 

Mark와 그의 전자 메일 간의 관계가 전자 메일 자체가 아니라 "주"라는 점을 지적하고자합니다. 다른 곳에서는 "주"속성을 저장할 수 없습니다.

지금, 나는이 값이 저장이 할 수 있지만, 문제는 같은 개체 속성을 만드는 방법이다 : 것은이

class Person { 

    (...) 

    /** 
    * @ORM\ManyToMany(targetEntity="Email") 
    * @ORM\JoinTable(name="people_emails", 
    *  joinColumns={@ORM\JoinColumn(name="person_id", referencedColumnName="id")}, 
    *  inverseJoinColumns={@ORM\JoinColumn(name="email_id", referencedColumnName="id", unique=true)} 
    *  ) 
    */ 
    private $primary_email; 

    /** 
    * @ORM\ManyToMany(targetEntity="Email") 
    * @ORM\JoinTable(name="people_emails", 
    *  joinColumns={@ORM\JoinColumn(name="person_id", referencedColumnName="id")}, 
    *  inverseJoinColumns={@ORM\JoinColumn(name="email_id", referencedColumnName="id", unique=true)} // A condition? 
    *  ) 
    */ 
    private $emails; 

    public function getPrimaryEmail() { 
     return $this->primary_email; // Single row limit? 
    } 

    public function getEmails() { 
     return $this->emails; 
    } 

    (...) 
} 

를, 난 정말 그냥 엔티티 속성으로 그것을 가지고 싶어요 모든 Person 모델에 대한 사용자 정의 repostory 함수를 작성할 필요없이 가능한 경우 사용할 수 있습니다.

아니면 완전히 잘못된 방법입니다. 나는 관절 식 컬럼에 따라 ManyToMany 단일 행 관계를 저장하고 싶습니다 :

{{person.primary_email.email}} 

가 요약하면 : 내가 좋아하는 나뭇 가지에 해당 속성을 사용하고 싶습니다.

어떻게 수행하나요?

+0

조인 테이블에 추가 데이터를 저장하려면 조인 테이블을 나타내는 새 엔터티를 만들고 해당 엔터티간에 일대 다 및 다 대일 관계를 추가하는 것이 좋습니다. 그리고 기본 전자 메일을 검색하려면 Doctrine Criteria를 사용하거나 반복적으로 전자 메일 모음을 필터링하고 Person 엔터티 내에 올바른 전자 메일을 반환 할 수 있습니다. – Kwido

+0

joinTable 기준에 따라 문자 그대로 결과를 가져오고 싶을 때 루핑은 문제가되지 않습니다. Thx – jakubplus

+0

루핑 문제가 귀하의 실수입니다. 루핑은 그다지 느리지 않으며 교리에서 원하는 것을 할 수있는 방법이 없습니다. 특히 데이터베이스 모델이 실제로 여러 개의 메인이있는 것을 제한하지 않는다는 것을 고려하지 마십시오. 유일한 해결책은 기본 속성을 전자 메일 엔터티를 참조하는 직접 ManyToOne로 만들어 기본 전자 메일에 대한 조인 테이블을 사용하지 않는 것입니다. – TFennis

답변

1

다양한 방법으로 디자인을 선택할 수 있습니다. 두 가지 조인 테이블을 사용하여이 작업을 수행 할 수있는 방법 중 하나는 외장 키를 사용하려는 경우 두 가지가 필요합니다.

<?php 

interface AddressLink 
{ 
    public function getEmail(); 
    public function isMain(); 
} 


trait EmailAddressOwner 
{ 
    protected abstract function getAddressLinks(); 

    public function getPrimaryEmailAddress() 
    { 
     return $this->getAddressLinks()->filter(function (AddressLink $addressLink) { 
      return $addressLink->isMain(); 
     })->first(); 
    } 

    public function getEmailAddresses() 
    { 
     return $this->getAddressLinks()->map(function (AddressLink $addressLink) { 
      return $addressLink->getEmail(); 
     }); 
    } 
} 

class PersonEmailAddress implements AddressLink 
{ 
    private $person; // ManyToOne 
    private $email; // ManyToOne 
    private $main; // bool 
} 

class CompanyEmailAddress implements AddressLink 
{ 
    private $company; // ManyToOne 
    private $email; // ManyToOne 
    private $main; // bool 
} 


class Email 
{ 
    private $id; 
    private $address; 
} 

class Person 
{ 
    /** 
    * @ORM\OneToMany(targetEntity="PersonEmailAddress") 
    */ 
    private $emailAddressLinks; 

    use EmailAddressOwner; 

    public function getAddressLinks() 
    { 
     return $this->emailAddressLinks; 
    } 

} 

class Company 
{ 
    /** 
    * @ORM\OneToMany(targetEntity="CompanyEmailAddress") 
    */ 
    private $emailAddressLinks; 

    use EmailAddressOwner; 

    public function getAddressLinks() 
    { 
     return $this->emailAddressLinks; 
    } 
} 

또 다른 방법은 Email 엔티티 한 ManyToMany 관계와 기본 전자 메일 주소에 대해 하나 개의 ManyToOne 관계를 포함하는 것입니다.

는 나뭇 가지에 당신이

{{ person.primaryEmail.email }} 

을 할 경우 그것은 실제로 사람 개체에 getPrimaryEmail() 메소드를 호출 줘야 코멘트에서 질문에 대답합니다. 위에서 설명한대로 구현할 수 있습니다. 그렇게하면 추가 속성이 필요하지 않습니다.

+0

몇 가지 설명을 추가했습니다. 문제는 이미 OTM 및 MTO가 존재한다는 것입니다. 문제는이 관계를 가능한 가장 단순한 방법으로 "사용"하는 것입니다. – jakubplus

+0

ORM \ WhereJoinColumn (name = "main", value = "1") – jakubplus

+0

짧게'{{person.primaryEmail}}'에서 내 대답을 업데이트했습니다. 실제로 호출 할 것입니다. 내 대답처럼'filter() -> first()'로 구현할 수있는'person-> getPrimaryEmail()'을 사용한다. – TFennis