laravelbrasil / forum

Ama Laravel? Torne se um Jedi e Ajude outros Padawans
GNU General Public License v3.0
251 stars 13 forks source link

Usando Eloquent em diferentes tabelas #98

Open ronicec opened 7 years ago

ronicec commented 7 years ago

Olá galera!!!

Problema Encontrado

Estou com uma dúvida no seguinte ponto. Tenho 3 tabelas:

Tabela A Tabela B (posso ter vários ID da tabela A) Tabela C. (posso ter vários ID da tabela B)

O relacionamento é: A => B => C

Nesse caso para recuperar um item lá na tabela C, eu preciso iniciar pela A, depois passar pela B e assim chegar no resultado da C. O problema é que não eu não quero fazer um select usando JOIN mas sim usando algo mais nativo e mais 'elegante' para retornar esses dados.


Abordagem

Na model da tabela A eu fiz:

public function tabelaB() {
        return $this->belongsToMany(TabelaB::class, 'tabela_b', 'id', 'id_a');
    }

Na model da tabela B eu fiz:

public function tabelaC() {
        return $this->belongsToMany(TabelaC::class, 'tabela_c', 'id_b', 'id_b');
    }

Qual que seria a minha ideia: Para retornar um dado da tabela A que tem vinculo até na tabela C ficaria algo:

$result = TabelaA::find($id_a)-> tabelaB-> tabelaC;

Mas ai que está o problema ele me retorna o seguinte erro:

"API method not found or arguments are invalidProperty [tabelaC] does not exist on this collection instance."

Se eu colocar até essa parte:

$result = TabelaA::find($id_a)-> tabelaB;

Funciona ele me retorna no caso os dados da tabela B no caso que tem referencia com a tabela A. Porem com a Tabela C não funciona e da o erro acima.

Agradeço a ajuda!


deleugpn commented 7 years ago

O problema é que tabelaB não é um item e sim uma coleção de itens, então vc não pode fazer ->tabelaB->tabelaC.

O que você quer se chama with.

$result = TabelaA::with(['tabelaB', 'tabelaC'])->find($id_a);
ronicec commented 7 years ago

@deleugpn Agradeço a sua ajuda, porém ele me retornou os dados da tabela A e B os dados da tabela C não foi retornado..

Até então o resultado que tive foi:

"result": {
        "id": 447,
        "name": "TABELA A",
        "created_at": "2017-04-18 12:20:20",
        "updated_at": "2017-04-18 12:47:15",
        "deleted_at": null,
        "tabelaB": [
            {
                "id": 7776,
                "name": "DADOS B",
                "created_at": "2017-04-18 11:20:37",
                "updated_at": "2017-04-18 11:20:37",
                "deleted_at": null,
                "pivot": {
                    "id": 447,
                    "id": 7776
                }
            }
       ]
}

Os dados da tabela C não vieram, porque?

deleugpn commented 7 years ago

Você precisa adicionar no modelo da Tabela A um hasManyThrough que aponta para o modelo C através do Modelo B.

ronicec commented 7 years ago

@deleugpn Pera, não consegui compreender.. hahahah Teria como você me dar um exemplo?

Obrigadoo!

sayhicoelho commented 7 years ago

Olá, @ronicec! Aproveitando a resposta do nosso amigo @deleugpn, dê uma olhada na documentação do Laravel: https://laravel.com/docs/5.4/eloquent-relationships#has-many-through

davidrtpereira commented 7 years ago

@deleugpn,

O exemplo de @ronicec não funcionado, pois o with retorna apenas os relacionamento definidos no model utilizando.

O método belongsToMany retorna dados de uma para outra apenas utilizando a tabela intermediária como "ponte"

Por exemplo:

class TabelaA extends Model{ public function tabelaC(){ return $this->belongsToMany('TabelaC', 'nome_da_tabela_intermediaria') } // Nome da tabela intermediária seria a TabelaB }

Há duas maneiras para solucionar esta questão, seria definindo o relacionamento acima, ou utilizando no with.

No with ficaria da seguinte maneira: TabelaA::with(['tabelaB.tabelaC'])->find($seuID);

Lembrando que para o with funcionar corretamente, no model da TabelaB deve existir o método "tabelaC", que deve fazer o seu relacionamento correspondente a tabela.

O with se aplica também quando definido o método tabelaC no model da TabelaA. Ex: TabelaA::with(['tabelaC'])->find($seuID);