2012-03-06 2 views
0

연결에 저장된 메타 데이터에 액세스 할 내가 3 개 테이블이 다음 LinkingAuthorBook 테이블을 사용하여 저자와 책 사이의 M : Doctrine docs를 통해 노트 당교리 테이블

# schema.yml 
Author: 
    connection: store-rw-library 
    tableName: lib_author 
    actAs: { Timestampable: ~ } 
    columns: 
    id: 
    type: integer(4) 
    unsigned: 1 
    primary: true 
    autoincrement: true 
    name: 
    type: string(50) 
    notnull: true 

Book: 
    connection: store-rw-library 
    tableName: lib_book 
    actAs: { Timestampable: ~ } 
    columns: 
    id: 
    type: integer(4) 
    unsigned: 1 
    primary: true 
    autoincrement: true 
    name: 
    type: string(50) 
    notnull: true 
    relations: 
    Author: 
     class: Author 
     foreignAlias: Books 
     refClass: LinkingAuthorBook 

LinkingAuthorBook: 
    connection: store-rw-library 
    tableName: lib_linking_author_book 
    columns: 
    author_id: 
     type: integer(4) 
     unsigned: 1 
     primary: true 
    book_id: 
     type: integer(4) 
     unsigned: 1 
     primary: true 
    created_at: 
     type: timestamp(25) 
     notnull: true 
    relations: 
    Author: 
     foreignAlias: AuthorBooks 
    Book: 
     foreignAlias: AuthorBooks 

을, 나는 M과 같은 관계를 설립했다.

지금, 나는 한 쿼리에서 특정 저자에 의해 저술 된 모든 책을 얻기 위해 노력하고, 뭔가 같은 :

class AuthorTable 
{ 
    public function getAuthor($id) 
    { 
     $q = Doctrine_Query::create() 
      ->select('a.id AS author_id') 
      ->addSelect('a.name AS author_name') 
      ->addSelect('b.AuthorBooks') 
      ->from('Author a') 
      ->innerJoin('a.Books b') 
      ->where('a.id = ?', $id); 

     $result = $q->fetchArray();    
    } 
} 

위 DQL 구조에서 결과 쿼리 :

SELECT 
    m.id AS m__id, 
    m.name AS m__1, 
    m2.id AS m2__id, 
    m2.name AS m2__1, 
    m.id AS m__0, 
    m.name AS m__1 
FROM 
    lib_author m 
INNER JOIN 
    lib_linking_author_book m3 ON (m.id = m3.author_id) 
INNER JOIN 
    lib_book m2 ON m2.id = m3.book_id 
WHERE 
    (m.id = '163') 

위의 쿼리에서 조인을 올바르게 수행하고 있지만 schema.yml 파일에 설정된 LinkingAuthorBook.created_at 메타 데이터 열에 어떻게 액세스합니까?

메타 데이터 열에 액세스 할 수있는 유일한 방법은 명시적인 innerJoinLinkingAuthorBook (연결된 book_link 별칭 포함)에 추가하는 것이었지만 이로 인해 결과 SQL에 또 다른 조인이 발생했습니다. 원본 쿼리에서 필요한 데이터에 액세스 할 수 있으므로 이해가되지 않습니다.

- 업데이트 (2012년 3월 7일) - 루프, 나는로부터 메타 데이터를 결합 할 수 없습니다 저자에 속하는를 통해 모든 책을 반복 I 설치하면 문제가 여전히 발생

LinkingAuthorBook 테이블 또는 다른 테이블을 강제로 Book 테이블.

업데이트 쿼리 : LinkingAuthorBook에서

$q = Doctrine_Query::create() 
    ->from('Author a') 
    ->innerJoin('a.Books b') 
    ->innerJoin('b.LinkingAuthorBook ab ON a.id = ab.author_id AND b.id = ab.book_id') 
    ->where('a.id = ?', $id); 

예 루프 -> 도서 :

foreach ($author->getLinkingAuthorBook() as $link) { 

    // Works fine, no extra query 
    var_dump($link->getCreatedAt()); 

    // Forces an extra query, even though 'name' is the column name 
    // So even though doctrine uses lazy-load, it should be able to 
    // get this data from the original query 
    var_dump($link->getBook()->getName()); 
} 

그리고 책의 다음 루프 같은 -> LinkingAuthorBook :

foreach ($author->getBook() as $book) { 

    // Forces extra query 
    var_dump($book->getLinkingAuthorBook()->getCreatedAt()); 

    // No extra query 
    var_dump($book->getName()); 
} 

내 해결 방법 :

그래서 지금

class Book 
{ 
    public $meta; 
} 

class AuthorTable 
{ 
    public function getAuthor($id) 
    { 
     $q = Doctrine_Query::create() 
      ->from('Author a') 
      ->innerJoin('a.Books b') 
      ->innerJoin('b.LinkingAuthorBook ab ON a.id = ab.author_id AND b.id = ab.book_id') 
      ->where('a.id = ?', $id); 

     $author = $q->fetchOne(); 

     // Manually hydrate Book Meta 
     foreach ($author->getLinkingAuthorBook() as $authorBook) { 
      $authorBooks[$authorBook->getId()] = $authorBook; 
     } 

     foreach ($author->getBook() as $book) { 
      $book->meta = $authorBooks[$book->getId()]; 
     } 
    } 
} 
, 내가 추가 쿼리를 시작하지 않고, 메타와 함께, 책을 반복 할 수 있습니다

foreach ($author->getBook() as $book) { 

    // No extra query 
    var_dump($book->meta->getCreatedAt()); 

    // No extra query 
    var_dump($book->getName()); 
} 

- 업데이트 (2012년 3월 8일) -

그래서 내가 할 수 있었다 다음 코드에서 그것을 증명하기 :

foreach ($author->getBooks() as $book) 
{ 
    echo $book->getName().'- '.$book->LinkingAuthorBook[0]->getCreatedAt().'<br/>'; 
} 

각각의 반복은 새 쿼리가 createdAt 값을 얻기 위해 발행하는 원인이되었다. 내가 MySQL의에서 다음 명령을 실행하여 이런 짓을 :

mysql> set global log_output = 'FILE'; 
mysql> set global general_log = 'ON'; 
mysql> set global general_log_file = '/var/log/mysql/queries.log'; 

은 그 때 나는 /var/log/mysql/queries.log 꼬리과 추가 쿼리가 생성되는 것을 볼 수 있었다. 그래서, 내가 말할 수있는 한, 초기 쿼리 후에 Book :: Meta 객체를 수동으로 수화시키는 것이 다른 쿼리를 발행 할 필요없이 메타 데이터에 접근 할 수있는 유일한 방법이다.

+0

롤 (Lol)은 이미 Google에서 검색했습니다. 순환 참조 ftw. –

답변

1

나의 제안 : 당신이 정말 필요

//one query for fetching an Author, his books and created_at for the each book 
$q = Doctrine_Query::create() 
      ->from('Author a') 
      ->innerJoin('a.Books b') 
      ->innerJoin('b.LinkingAuthorBook ab ON a.id = ab.author_id AND b.id = ab.book_id') 
      ->where('a.id = ?', 1); 

$author = $q->fetchOne(); 

echo 'Author: '.$author->getName().'<br/>'; 
echo 'Books: <br/>'; 
foreach ($author->getBooks() as $book) 
{ 
    echo $book->getName().'- '.$book->LinkingAuthorBook[0]->getCreatedAt().'<br/>'; 
} 

하나의 쿼리.

+0

다른 쿼리가 실행됩니까? Object를 사용하여 배열에서 ORM으로 이식 된 페이지가 2 개의 쿼리에서 21로 갔다는 것을 알아 냈습니다. –

+0

그래서 fetchArray()를 fetchOne()으로 전환하여 객체에 액세스하여 설명 된 유창한 인터페이스를 지원합니다 위. 'var_dump ($ result-> getId()); '를 할 수는 있지만'var_dump ($ result-> getName()); 할 때 다른 쿼리를 추가합니다 : SELECT m.id AS m__id, m.name AS m__name, m.created_at AS m__created_at, m.updated_at m_updated_at from lib_author m WHERE (m.id = '163') LIMIT 1'. 이것은 이해가되지 않습니다. 데이터를 검색하려고 할 때 알려진 접근자를 던져 다른 쿼리를 실행하는 이유는 무엇입니까? –

+0

Doctrine은 Lazy Load 패턴을 사용합니다. 귀하의 질의에서 이름 대신 author_name을 선택하십시오 :'a.name AS author_name' '$ result-> getAuthorName()'을 사용하여 액세스 할 수 있습니다. '$ result-> getName()'을 사용하여 name에 접근하려고하면 doctrine은 다른 쿼리를 생성하여 이름을 검색합니다. – Mikhail