felini 0 Denunciar post Postado Fevereiro 6, 2011 Estou migrando o sistema para dentro do ZEND e me deparei com a seguinte situação: Tenho a seguinte query: SELECT cat.nome nome_categoria, sub . * FROM categorias cat INNER JOIN subcategorias sub ON cat.id = sub.categoria_id ORDER BY cat.nome E ao passar pra dentro do framework, eu até achei simples, de acordo com a documentação: http://framework.zend.com/manual/en/zend.db.select.html No entanto pra criar esta query, eu preciso de fato criar o objeto Zend_Db_Select? Lá eu tenho o seguinte exemplo: $db = Zend_Db::factory( ...options... ); $select = $db->select(); Eu consigo criar esta query, sem ter de passar os dados através do factory()? Eles já estão configurados no application.ini. Eu criei um protótipo, segue abaixo: $rs = $this->getDbAdapter()->select() ->from(array('cat' => 'categorias'), array('nome')) ->join(array('sub' => 'subcategorias'), array('cat.id = sub.categoria_id')); Valeu pela ajuda. Abraço, Compartilhar este post Link para o post Compartilhar em outros sites
Matias Rezende 50 Denunciar post Postado Fevereiro 7, 2011 Como você fez o ORM? Ou não vai fazer mapeamento? Como você definiu no application.ini? O que você está passando para a factory? Carlos Eduardo Compartilhar este post Link para o post Compartilhar em outros sites
felini 0 Denunciar post Postado Fevereiro 7, 2011 Não fiz o mapeamento! Tu acha melhor fazê-lo? Meu 'application.ini' está da seguinte forma: [production] phpSettings.display_startup_errors = 0 phpSettings.display_errors = 0 includePaths.library = APPLICATION_PATH "/../library" bootstrap.path = APPLICATION_PATH "/Bootstrap.php" bootstrap.class = "Bootstrap" appnamespace = "Application" resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers" resources.frontController.params.displayExceptions = 0 ; Banco de Dados resources.db.adapter = "PDO_MYSQL" resources.db.params.host = "localhost" resources.db.params.dbname = "store" resources.db.params.username = "root" resources.db.params.password = "" Meu factory está da seguinte forma: $db = Zend_Db::factory('Pdo_Mysql', array( 'host' => 'localhost', 'username' => 'root', 'password' => '', 'dbname' => 'store' )); No entanto não queria utilizar o factory. Queria saber como fazer a consulta SQL sem ter que 'conectar' no banco e ao invés disso, utilizar as configs do application.ini Valeu! Compartilhar este post Link para o post Compartilhar em outros sites
Matias Rezende 50 Denunciar post Postado Fevereiro 7, 2011 O mapeamento é interessante, mas não é obrigatório. Vai depender da sua aplicação. Ao fazer como você descreve no application.ini, não é necessário utilizar o Factory. Você pode utilizar getDefaultAdapter(); Algo assim: $db = Zend_Db_Table::getDefaultAdapter (); $select = $db->select (); Isto considerando que você não esteja estendendo a classe Zend_Db_Table_Abstract. Caso esteja, não é necessário fazer nada disto. Só utilizar $this->select(). Carlos Eduardo Compartilhar este post Link para o post Compartilhar em outros sites
felini 0 Denunciar post Postado Fevereiro 7, 2011 Minha classe Application_Model_DbTable_SubCategorias esta estendendo da Zend_Db_Table_Abstract, Então, na Mapper, eu faço o seguinte: public function fetchAll(){ $select = $this->getDbTable()->select(); $select->from(array('cat' => 'categorias'),array('nome')); $select->join(array('sub' => 'subcategorias'),array('cat.id = sub.categoria_id')); $resultado = $this->fetchAll($select); return $resultado; } Quando vou na view e mando printar o fetchAll, me aparece o seguinte resultado: Fatal error: Maximum function nesting level of '100' reached, aborting! in C:\wamp\library\Zend\Db\Table\Abstract.php on line 889 Compartilhar este post Link para o post Compartilhar em outros sites
Matias Rezende 50 Denunciar post Postado Fevereiro 7, 2011 Não consegui entender como você está fazendo. Poste a Mapper completa. Qual versão do Zend Framework você tá usando? Carlos Eduardo Compartilhar este post Link para o post Compartilhar em outros sites
felini 0 Denunciar post Postado Fevereiro 7, 2011 Mapper <?php /** * Mapeamento da tabela SUBCATEGORIAS * Funções para inclusao, exclusao e edicao * * @author Matheus * @version 1.0 */ class Application_Model_SubCategoriasMapper { protected $_dbTable; public function setDbTable($dbTable) { // Verifica se o parâmetro é mesmo uma string if (is_string($dbTable)) { $dbTable = new $dbTable; } // Testa se o objeto é uma instancia de uma classe especifica if (!$dbTable instanceof Zend_Db_Table_Abstract) { // lanca excessao throw new Exception("Gateway Inválido"); } // se passar nos dois testes, aceita a atribuicao $this->_dbTable = $dbTable; // retorna o objeto return $this; } public function getDbTable() { // testa pra saber se a instancia criada pelo setDbTable é nula if (NULL === $this->_dbTable) { $this->setDbTable("Application_Model_DbTable_SubCategorias"); } return $this->_dbTable; } public function fetchAll(){ $select = $this->getDbTable()->select(); $select->from(array('cat' => 'categorias'),array('nome')); $select->join(array('sub' => 'subcategorias'),array('cat.id = sub.categoria_id')); $resultado = $this->fetchAll($select); var_dump($select); /* $results = array(); foreach ($resultado AS $row){ $entry = new Application_Model_SubCategorias(); $entry->setId($row->id); $entry->setNomeCategoria($row->nome_categoria); $entry->setNome($row->nome); $results[] = $entry; } */ return $resultado; } /** * Método para cadastrar subcategorias * * @param array $dados */ public function cadastrar($dados){ $this->getDbTable()->insert($dados); } /** * Método que exclui a subcategoria que é passada pelo IDs * * @param int $id */ public function excluir($id){ $table = $this->getDbTable(); $where = $table->getAdapter()->quoteInto('id = ?',$id); $table->delete($where); } } ?> DbTable <?php class Application_Model_DbTable_SubCategorias extends Zend_Db_Table_Abstract { protected $_name = "subcategorias"; } ?> Compartilhar este post Link para o post Compartilhar em outros sites
Matias Rezende 50 Denunciar post Postado Fevereiro 7, 2011 Uhn... Acho que aqui tem coisa errada... $resultado = $this->fetchAll($select); Quando você faz $this->fetchAll(), está chamando o próprio método (recursividade). Isto é interessante, mas acredito que no seu caso você queria pegar o método fetchAll() da classe Application_Model_DbTable_SubCategorias. Então, seria: $resultado = $this->getDbTable()->fetchAll($select). -------------------------------- Além disto, veja que você utiliza no seu application.ini o seguinte: appnamespace = "Application" Então, não há necessidade de utilizar Application_* no nome das classes. Outra sugestão que eu faço, já que você está fazendo com Mapper, é utilizar uma classe Pai (AbstractMapper) que vai abstrair os métodos getDbTable e setDbTable, já que eles serão exatamente iguais em qualquer Mapper que você fizer, sendo diferente somente o nome da classe que será instanciada. Para isto, eu passaria o nome em uma propriedade $_dbTableName, definida na classe filha. Carlos Eduardo Compartilhar este post Link para o post Compartilhar em outros sites
felini 0 Denunciar post Postado Fevereiro 7, 2011 Fala ae Carlos, cara muito obrigado pelas dicas e ajuda que está me dando! Estou muito grato mesmo. Experimentei fazer da forma como tu falou, no entanto não sei o que acontece de errado. Primeiramente, deixei o método fetchAll() da seguinte forma: $select = $this->getDbTable()->select() ->from(array('cat' => 'categorias'),array('nome')) ->joinInner(array('sub' => 'subcategorias'),array('cat.id = sub.categoria_id')); $resultado = $this->getDbTable()->fetchAll($select); return $resultado; Desta forma, retorna a seguinte msg: Exception information: Message: Select query cannot join with another table Se eu tirar o $this->getDbTable() da var $select e deixar apenas $this->select() retorna o erro: Fatal error: Call to undefined method Application_Model_SubCategoriasMapper::select() in C:\wamp\www\loja\application\models\SubCategoriasMapper.php on line 40 Ou seja, ele não acha o método select() dentro de Model_SubCategoriasMapper. Então, resolvi fazer da seguinte forma: $db = $this->getDbTable()->getDefaultAdapter(); $select = $db->select() ->from(array('cat' => 'categorias'),array('nome')) ->join(array('sub' => 'subcategorias'),array('cat.id = sub.categoria_id')); $resultado = $this->getDbTable()->fetchAll($select); return $resultado; Mas isso me retorna um erro de SQL: Message: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 Compartilhar este post Link para o post Compartilhar em outros sites
Matias Rezende 50 Denunciar post Postado Fevereiro 8, 2011 Fala ae Carlos, cara muito obrigado pelas dicas e ajuda que está me dando! Estou muito grato mesmo. :joia: Sobre o seu problema, o primeiro código é o mais correto, mas o Zend Framework tem um bug (não vou achar agora o bug tracing, mas depois você procura). Para que queries com join funcionem, você deve fazer assim: $select = $this->getDbTable()->select()->setIntegrityCheck(false) ->from(array('cat' => 'categorias'),array('nome')) ->joinInner(array('sub' => 'subcategorias'),array('cat.id = sub.categoria_id')); $resultado = $this->getDbTable()->fetchAll($select); return $resultado; Veja se assim funciona. Carlos Eduardo Compartilhar este post Link para o post Compartilhar em outros sites
felini 0 Denunciar post Postado Fevereiro 8, 2011 E ae Carlos, Na verdade não funcionou, mas era um erro de sintaxe. Vou colocar aqui pra alertar o pessoal: $select = $this->getDbTable()->select()->setIntegrityCheck(false) ->from(array('cat' => 'categorias'),array('nome')) ->joinInner(array('sub' => 'subcategorias'),array('cat.id = sub.categoria_id')); $resultado = $this->getDbTable()->fetchAll($select); return $resultado; O correto é não ter o ultimo array() - array('cat.id = sub.categoria_id'), deve ficar apenas desta forma: $select = $this->getDbTable()->select()->setIntegrityCheck(false) ->from(array('cat' => 'categorias'),array('nome')) ->joinInner(array('sub' => 'subcategorias'), 'cat.id = sub.categoria_id'); $resultado = $this->getDbTable()->fetchAll($select); return $resultado; Dai funcionou. Estava tentando recuperar o NOME da categoria associada à subcategoria, então meu select ficou desta forma: $select = $this->getDbTable()->select() ->from(array('cat' => 'categorias')) ->join(array('sub' => 'subcategorias'), 'sub.categoria_id = cat.id', array ('categoria_nome' => 'cat.nome', 'categoria_id' => 'cat.id', 'subcategoria_nome' => 'sub.nome', 'subcategoria_id' => 'sub.id')) ->setIntegrityCheck(false); $resultado = $this->getDbTable()->fetchAll($select); Porém, ele me retorna este resultado: array 0 => array 'id' => string '7' (length=1) 'nome' => string 'Bijuteria' (length=9) 'categoria_nome' => string 'Bijuteria' (length=9) 'categoria_id' => string '7' (length=1) 'subcategoria_nome' => string 'Anel' (length=4) 'subcategoria_id' => string '4' (length=1) Se reparar, a posição id e nome são a mesma de categoria_nome e categoria_id. Tu sabe porque isso ocorre? Isso é detalhe, mas é curiosidade.Fiz desta forma de acordo com a documentação http://framework.zen....db.select.html , se tiver uma dica, ela é muito bem vinda. Mais uma vez, muito obrigado pela força. Abraço, Compartilhar este post Link para o post Compartilhar em outros sites
Matias Rezende 50 Denunciar post Postado Fevereiro 8, 2011 Então... O objeto Select tem um método __toString(), que é chamado ao se tratar o objeto como uma string. Este método imprime a query como ela está no momento. Faça um teste: $select = $this->getDbTable()->select() ->from(array('cat' => 'categorias')) ->join(array('sub' => 'subcategorias'), 'sub.categoria_id = cat.id', array ('categoria_nome' => 'cat.nome', 'categoria_id' => 'cat.id', 'subcategoria_nome' => 'sub.nome', 'subcategoria_id' => 'sub.id')) ->setIntegrityCheck(false); echo $select; exit; $resultado = $this->getDbTable()->fetchAll($select); Isto é muito útil quando estamos fazendo debug e para analisar as querys enviadas, buscando melhorar a performance. No seu caso, isto ocorre porque você não define quais campos quer buscar da tabela no from, então ele busca *. Caso não queira nenhum campo, coloque array(). Carlos Eduardo Compartilhar este post Link para o post Compartilhar em outros sites
felini 0 Denunciar post Postado Fevereiro 9, 2011 Entendi! Cara, muito obrigado pela força! Vou seguir desenvolvendo aqui agora que desempaquei nessa parte. Abraço, Matheus Compartilhar este post Link para o post Compartilhar em outros sites