Eloquent: Retornar dados de relacionamento com campos com mesmo nome

2,326 views
Skip to first unread message

Fernando Friedrich

unread,
Mar 5, 2015, 6:59:24 AM3/5/15
to laravel...@googlegroups.com
Bom dia,

Sou iniciante no Laravel e estou gostando muito do framework, porém me surgiu um problema.
Tenho três tabelas, cidades, estados e paises. Nela tenho os esquemas:

Pais:
id
codigoibge
sigla
nome

Estados:
id
pais_id
codigoibge
sigla
nome

Cidades:
id
estado_id
codigoibge
cep
nome

Os modelos estou anexando, mas estão certinhos, belongsTo, hasMany etc...

Meu problema encontra-se em retornar uma pesquisa com where na cidade, ordenando por cidade e estado, por exemplo quero que retorne:
Cachoeirinha/PE
Cachoeirinha/RS
Cachoeirinha/TO

Tentei inicialmente isto:
$cidades = Cidade::where('nome', 'LIKE', Input::get('term') . '%')->orderBy('nome', 'asc')->get();

Porém não consigo selecionar a sigla do estado para ordenar.

Então usei um join, funcionou perfeito retornando todos os dados, consigo ordenar por sigla, porem quando eu retorno o ID, nome ou codigoIBGE ele retorna o do estado.

Como posso solucionar ou fazer este select pelo Eloquent?
Cidade.php
Estado.php
Pais.php

Lucas Gois

unread,
Mar 5, 2015, 7:15:08 AM3/5/15
to laravel...@googlegroups.com
$cidades = Cidade::where('nome', 'LIKE', Input::get('term') . '%')->orderBy('estado.nome', 'asc')->get();

no caso estou presumindo que estados é o nome do seu relacionamento no model Cidade.

Não testei na verdade, mas acho que isso ficaria correto.

--
Você recebeu essa mensagem porque está inscrito no grupo "Laravel Brasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para laravel-brasi...@googlegroups.com.
Para mais opções, acesse https://groups.google.com/d/optout.



--
Att
Lucas Padilha Gois

Fernando Friedrich

unread,
Mar 5, 2015, 7:56:30 AM3/5/15
to laravel...@googlegroups.com
Lucas, obrigado pela resposta tão rápida.

Já tentei o que você sugeriu e ele me retorna um erro de que não existe o campo estados, na verdade ali estou ordenando apenas pela cidade mesmo, mas preciso adicionar ordenação por:
cidades.nome
estados.sigla


Sem mais, agradeço sua atenção e coloco-me à disposição para esclarecimentos adicionais.
Cordialmente,
Fernando Friedrich
Cel.: (51) 8442-8866
E-mail/MSN: fern...@hadder.com.br
Skype: rainzart
HaDDeR - http://www.hadder.com.br

--
Você recebeu essa mensagem porque está inscrito em um tópico no grupo "Laravel Brasil" dos Grupos do Google.
Para cancelar inscrição nesse tópico, acesse https://groups.google.com/d/topic/laravel-brasil/Wt6Q-eq2tIY/unsubscribe.
Para cancelar inscrição nesse grupo e todos os seus tópicos, envie um e-mail para laravel-brasi...@googlegroups.com.

Lucas Gois

unread,
Mar 5, 2015, 7:59:32 AM3/5/15
to laravel...@googlegroups.com
$cidades = Cidade::where('nome', 'LIKE', Input::get('term') . '%')->with('estado')->orderBy('estado.nome', 'asc')->get();

e assim?

Daniel Batista Lemes

unread,
Mar 5, 2015, 8:15:04 AM3/5/15
to laravel...@googlegroups.com

Cola o relacionamento ai

Fernando Friedrich

unread,
Mar 5, 2015, 8:27:38 AM3/5/15
to laravel...@googlegroups.com
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'estado.nome' in 'order clause' (SQL: select * from `cidades` where `nome` LIKE Cach% order by `estado`.`nome` asc)

:( sinceramente até agora não entendi muito bem o que é o "with" e pra que serve... Mas pelo que pude perceber, tb não rolou...

Se eu fizer com join assim:
$cidades = Cidade::join('estados', 'estados.id', '=', 'cidades.estado_id')
                            ->where('cidades.nome', 'LIKE', Input::get('term') . '%')
                            ->orderBy('cidades.nome', 'asc')
                            ->orderBy('estados.nome', 'asc')
                            ->get();

Funciona mas não consigo retornar os dados da cidade.

Sem mais, agradeço sua atenção e coloco-me à disposição para esclarecimentos adicionais.
Cordialmente,
Fernando Friedrich
Cel.: (51) 8442-8866
E-mail/MSN: fern...@hadder.com.br
Skype: rainzart
HaDDeR - http://www.hadder.com.br

Fernando Friedrich

unread,
Mar 5, 2015, 8:28:48 AM3/5/15
to laravel...@googlegroups.com
Daniel, o relacionamento mandei em anexo no primeiro e-mail mas segue:

Estado:

public function cidades()
    {
        return $this->hasMany('App\Cidade');
    }


Cidade:

public function estado()
    {
        return $this->belongsTo('App\Estado');
    }

Sem mais, agradeço sua atenção e coloco-me à disposição para esclarecimentos adicionais.
Cordialmente,
Fernando Friedrich
Cel.: (51) 8442-8866
E-mail/MSN: fern...@hadder.com.br
Skype: rainzart
HaDDeR - http://www.hadder.com.br

Renan Paes Leme

unread,
Mar 5, 2015, 9:13:25 AM3/5/15
to laravel...@googlegroups.com
Já tentou usar o  ->groupBy('estados.nome')?

Abraços.

Renan Paes Leme

unread,
Mar 5, 2015, 9:20:49 AM3/5/15
to laravel...@googlegroups.com
$cidades = Cidade::with('estado')->where('nome', 'LIKE', '%'. Input::get('term') . '%')->orderBy('cidade.nome', 'asc')->groupBy('estado.nome')->get();

O with serve para já pegar as relações, se você pegar $cidades = Cidade::with('estado');

No $cidades[1]->estado->nome, vai retornar o estado a que pertence essa cidade. Tente dar um dd($cidades) que você vai entender o que eu to falando :)

Não estou com Laravel aqui para testar, mais acho que assim funcionará :P

Fernando Friedrich

unread,
Mar 5, 2015, 10:29:41 AM3/5/15
to laravel...@googlegroups.com
Renan, não funcionou :(
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'estado.nome' in 'group statement' (SQL: select * from `cidades` where `nome` LIKE %Cachoeiri% group by `estado`.`nome` order by `cidade`.`nome` asc)

Pelo que estou entendendo, quando você chama a relação pela classe Cidade, o Eloquent faz um select com a chave estrangeira na tabela estados e retorna os dados, mas não inclui a tabela no select inicial, sendo assim acho que só vou conseguir ordenar se for por join, ai sim o Eloquent faz um inner join e tal, o problema é que como tenho colunas com o mesmo nome, ele retorna os dados da tabela que estou unindo.


Sem mais, agradeço sua atenção e coloco-me à disposição para esclarecimentos adicionais.
Cordialmente,
Fernando Friedrich
Cel.: (51) 8442-8866
E-mail/MSN: fern...@hadder.com.br
Skype: rainzart
HaDDeR - http://www.hadder.com.br

Oscar Dias

unread,
Mar 5, 2015, 1:55:39 PM3/5/15
to laravel...@googlegroups.com
Fernando,

Acho que a maneira que você estava fazendo é uma boa alternativa, só precisa de um select().
$cidades = Cidade::select('cidades.*', 'estados.nome as nome_estado')
                            ->join('estados', 'estados.id', '=', 'cidades.estado_id')
                            ->where('cidades.nome', 'LIKE', Input::get('term') . '%')
                            ->orderBy('cidades.nome', 'asc')
                            ->orderBy('estados.nome', 'asc')
                            ->get();

Tem que definir um select com os campos que você precisa e dar nomes diferentes para os campos do estado, ou então eles vão sobrescrever os campos da cidade.

Infelizmente com o with não tem como ordernar pela sigla do estado, pois o with faz o seguinte (mais ou menos - baseado no texto da documentação):
select * from cidades

select * from estados where id in (1, 2, 3, 4, 5, ...)
Ou seja, ele separa em duas queries, então não seria possível ordenar pelo estado.

Boa sorte

Renan Paes Leme

unread,
Mar 5, 2015, 4:20:10 PM3/5/15
to laravel...@googlegroups.com
É isso aí mesmo Oscar,

Eu esqueci que o with selecionava só as ids que ele necessitava, o que acabava quebrando o group.

Na query, se não me engano tem que trocar o 'estados.nome' pra 'nome_estado', pois foi criado a alias antes. :P

Abraços!

Fernando Friedrich

unread,
Mar 5, 2015, 4:55:39 PM3/5/15
to laravel...@googlegroups.com
Oscar, deu certo! :D
Só achei um pouco estranho no codigo como ficou, olha só:
$cidades = Cidade::select('cidades.*', 'estados.id as est_id', 'estados.codigoibge as est_codigoibge')

                            ->join('estados', 'estados.id', '=', 'cidades.estado_id')
                            ->where('cidades.nome', 'LIKE', Input::get('term') . '%')
                            ->orderBy('cidades.nome', 'asc')
                            ->orderBy('estados.nome', 'asc')
                            ->get();

Ai ele retornou legal!

Quando fui dar um foreach, achei curioso como acessei os dados, não modifiquei o foreach e o laravel já puxou certinho:
foreach($cidades as $value) {
            $data[] = array(
                    'display' => $value->nome,
                    'cid' => $value->id,
                    'cibge' => $value->codigoibge,
                    'value' => $value->nome . '/' . $value->estado->uf,
                    'eid' => $value->estado->id,
                    'eibge' => $value->estado->codigoibge,
                    'uf' => $value->estado->uf
            );
        }


O interessante é que consigo acessar o codigo IBGE do estado apenas usando $value->estado->codigoibge, imaginei que como defini um alias pro campo, o correto seria acessar por $value->est_codigoibge (que tambem funcionou!)


Agradeço a todos pelas ajudas!

Sem mais, agradeço sua atenção e coloco-me à disposição para esclarecimentos adicionais.
Cordialmente,
Fernando Friedrich
Cel.: (51) 8442-8866

Oscar Dias

unread,
Mar 6, 2015, 3:53:54 PM3/6/15
to laravel...@googlegroups.com
Dá uma conferida nas queries que estão sendo geradas usando $queries = DB::getQueryLog();. Quando você usa eu acho (não tenho certeza) que o Laravel vai ter q

--

Oscar Dias

unread,
Mar 6, 2015, 3:56:45 PM3/6/15
to laravel...@googlegroups.com
Opa... o email anterior foi sem querer.... concluindo:

Dá uma conferida nas queries que estão sendo geradas usando $queries = DB::getQueryLog();. Quando você usa $value->estado->codigoibge eu acho (não tenho certeza) que o Laravel vai ter que buscar a informação do estado para cada cidade, executando várias queries e diminuindo a performance. Como você já fez o join e selecionou os campos usando alias o ideal é usar o alias diretamente:
$value->est_codigoibge

Mas dá uma olhada nas queries depois do foreach para confirmar se ele executou mais queries que o necessário.

Abraço

Fernando Friedrich

unread,
Mar 6, 2015, 5:58:25 PM3/6/15
to laravel...@googlegroups.com
Oscar, muito obrigado pela sua informação, realmente fiz um teste e a cada registro o laravel faz um select estado where id = estado, sendo assim se você lista 20 cidade, são 21 queris, só pra testes fiz uma busca por a%, deu "só" mais de 400 querys :(

Não conhecia o DB::getQueryLog, mas tive que habilitar ele lá em vendor/laravel/framework/src/Illuminate/Database/Connection.php, não teria como configurar isto no arquivo de config? Estive procurando pelo google e só vi gente falando de configurar no Connection...

Sem mais, agradeço sua atenção e coloco-me à disposição para esclarecimentos adicionais.
Cordialmente,
Fernando Friedrich
Cel.: (51) 8442-8866
E-mail: fern...@hadder.com.br
Skype: rainzart
HaDDeR - http://www.hadder.com.br

--
Você recebeu essa mensagem porque está inscrito em um tópico no grupo "Laravel Brasil" dos Grupos do Google.
Para cancelar inscrição nesse tópico, acesse https://groups.google.com/d/topic/laravel-brasil/Wt6Q-eq2tIY/unsubscribe.
Para cancelar inscrição nesse grupo e todos os seus tópicos, envie um e-mail para laravel-brasi...@googlegroups.com.

Oscar Dias

unread,
Mar 6, 2015, 8:13:35 PM3/6/15
to laravel...@googlegroups.com
Eu uso o getQueryLog direto, sem necessidade de habilitar nada. Qual versão você está usando?

Na documentação fala sobre desabilitar (por questões de performance) usando DB::connection()->disableQueryLog();. Talvez tenha um comando parecido para habilitar...

Fernando Friedrich

unread,
Mar 6, 2015, 8:47:57 PM3/6/15
to laravel...@googlegroups.com
Estou usando a 5.0.133, como estou aprendendo e fazendo um projeto de testes que apenas alguns amigos vão utilizar, volta e meia dou um composer update

Sem mais, agradeço sua atenção e coloco-me à disposição para esclarecimentos adicionais.
Cordialmente,
Fernando Friedrich
Cel.: (51) 8442-8866
E-mail: fern...@hadder.com.br
Skype: rainzart
HaDDeR - http://www.hadder.com.br

Fernando Friedrich

unread,
Mar 6, 2015, 8:48:31 PM3/6/15
to laravel...@googlegroups.com
Ops, correção 5.0.13
Reply all
Reply to author
Forward
0 new messages