Zend Select com a auto juntar campos sobrescrevendo
-
19-09-2019 - |
Pergunta
Mensagens e comentários são armazenados na mesma tabela. Assim, para obter cada post e seus comentários que faça o seguinte:
$posts = $this->select()->setIntegrityCheck(false)
->from(array('post' => 'Posts'), array('*'))
->where('post.idGroup = ' . $idGroup)
->where('post.idTopic IS NULL')
->order('post.date DESC')
->limit($resultsPerPage, $resultsPerPage * ($page - 1))
->joinLeft(array('user' => 'Users'), 'post.idUser = user.idUser',
array('idUser', 'fname', 'lname', 'profileUrl', 'photoUrl'))
->joinLeft(array('comment' => 'Posts'), 'comment.idTopic = post.idPost')
->query()->fetchAll();
O problema é que a matriz resultante é plana e os dados comentário substitui os dados post, este é um exemplo do que é retornado:
[1] => Array
(
[idPost] => 13
[idTopic] => 11
[idGroup] => 1
[idUser] => 84
[postContent] => Hello my name is Mud.
[postUrl] => 13/hello-my-name-is-mud
[postVotes] =>
[postScore] =>
[date] => 2009-07-21 16:39:09
[fname] => John
[lname] => Doe
[profileUrl] => john-doe
[photoUrl] => uploads/userprofiles/0/84/pic84_14
)
O que nós gostaríamos que o resultado seja algo mais parecido com isto:
[1] => array(
[post] => array(
[0] => array(
idPost => 12,
postContent => This is a post...,
idGroup => 1
...
)
),
[user] => array(
[0] => array(
userName => JohnDoe
...
)
),
[comments] => array(
[0] => array(
idPost => 15,
postContent => This is a comment...,
idGroup => 1
...
),
[1] => array(
idPost => 17,
postContent => This is another comment...,
idGroup => 1
...
)
)
)
Alguma dica para outras soluções também é muito bem-vindos.
Graças.
Solução
Se você aliás todas as colunas na segunda juntar-se a mensagens (como idPost como child_idPost ... etc), você vai ter muitas linhas que são a linha pai com as colunas da segunda fila. Isso é sobre o mais próximo que você vai conseguir. Você pode, em seguida, pegar os dados dos pais da primeira linha, e depois percorrer as linhas subseqüentes para obter seus dados de um-para-muitos.
Caso contrário, basta fazer duas consultas, uma para o pai, um para as crianças. Pode ser mais rápido do que criar essa tabela de resultados grande de qualquer maneira.
Outras dicas
Zend não faz a sua forma preferida fácil, mas pode ser possível. Note, no entanto, que você está pedindo o servidor de banco de dados para fazer muito mais trabalho do que você realmente quer, porque o post e informações do usuário são duplicados para cada comentário. Justin é correto que uma segunda consulta é mais fácil e provavelmente mais rápido. No entanto, eu posso fornecer alguns ponteiros em direção a uma solução.
Para começar, considere o que você iria ficar usando o modo do Zend_Db::FETCH_NUM
buscar:
Array(
[0] => Array(
[0] => 12
[1] =>
[2] => 1
[3] => 84
[4] => This is a post...,
[5] => 12/this-is-a-post
[6] =>
[7] =>
[8] => 2009-07-21 16:39:09
[9] => 84
[10] => John
[11] => Doe
[12] => john-doe
[13] => uploads/userprofiles/0/84/pic84_14
[14] => 15
[15] => 12
[16] => 1
[17] => 79
[18] => This is a comment...,
[19] =>
[20] =>
[21] =>
[22] => 2009-07-21 17:40:10
),
[1] => Array(
[0] => 12
[1] =>
[2] => 1
[3] => 84
[4] => This is a post...,
[5] => 12/this-is-a-post
[6] =>
[7] =>
[8] => 2009-07-21 16:39:09
[9] => 84
[10] => John
[11] => Doe
[12] => john-doe
[13] => uploads/userprofiles/0/84/pic84_14
[14] => 17
[15] => 12
[16] => 1
[17] => 127
[18] => This is another comment...,
[19] =>
[20] =>
[21] =>
[22] => 2009-07-20 10:31:26
)
)
Depois de alguma forma você tem que vir acima com o mapeamento de números de coluna para nomes de tabelas e colunas:
Array(
[0] => post.idPost
[1] => post.idTopic
[2] => post.idGroup
[3] => post.idUser
[4] => post.postContent
[5] => post.postUrl
[6] => post.postVotes
[7] => post.postScore
[8] => post.date
[9] => user.idUser
[10] => user.fname
[11] => user.lname
[12] => user.profileUrl
[13] => user.photoUrl
[14] => comment.idPost
[15] => comment.idTopic
[16] => comment.idGroup
[17] => comment.idUser
[18] => comment.postContent
[19] => comment.postUrl
[20] => comment.postVotes
[21] => comment.postScore
[22] => comment.date
)
Esta é a parte onde fica complicado, porque a parte da tabela de que é fortemente específico para a interface de banco de dados, e nem sempre é possível. Porque ele está vinculado ao conjunto de resultados, o adaptador também será o melhor lugar para obtê-lo; que os meios de hacking aulas Zend, possivelmente, fornecendo sua própria classe de adaptador. Dependendo do seu banco de dados, as informações podem vir de:
- DOP:
PDOStatement->getColumnMeta
- Mysqli:
mysqli_fetch_field_direct
Outros adaptadores não pode ter uma maneira de obter o nome da tabela, infelizmente.
Sim, nós tivemos o mesmo problema, apenas blogging acabada sobre isso: http://www.kintek.com.au/blog/zend-db-and-joins/
Você precisa nomear cada campo de forma única, é um erro conhecido no Zend: http://framework.zend.com/issues/browse/ZF-6421?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel