Laravel Eloquent: Como obter apenas algumas colunas de tabelas unidas


102

Eu tenho 2 tabelas unidas no Eloquent: temas e usuários.

modelo de tema:

public function user() {
  return $this->belongs_to('User');
}

modelo de usuário:

public function themes() {
  return $this->has_many('Theme');
}

Minha chamada de API do Eloquent é a seguinte:

return Response::eloquent(Theme::with('user')->get());

O que retorna todas as colunas do tema (isso é bom) e todas as colunas do usuário (não está bem). Eu preciso apenas da coluna 'nome de usuário' do modelo de usuário, como posso limitar a consulta a isso?


Estou trabalhando em uma tarefa semelhante, posso saber se estou usando Responseque tipo de classe preciso importar?
Agnes Palit

Respostas:


103

Altere seu modelo para especificar quais colunas você deseja selecionar:

public function user() {
  return $this->belongs_to('User')->select(array('id', 'username'));
}

E não se esqueça de incluir a coluna à qual você está ingressando.


6
ótima resposta, também a dica sobre a inclusão da coluna join me economizou muito tempo!
greatwitenorth

E se em alguns lugares eu precisar apenas de id em vez de id e nome de usuário? Ainda tem que selecionar ambos?
Darius.V

Olá, a função de seleção tem a mesma função no construtor de consulta de modelo?
Gokigooooks de

4
Não acho que seja uma boa abordagem. Será uma espécie de codificação dos nomes das colunas. Todos os lugares retornarão apenas essas colunas. Em alguma outra API, posso precisar de mais algumas colunas, então isso não funcionará aqui. Acho que usar QueryBuilder é a opção aqui.
Aman Sura

2
Esta é uma abordagem dramática, pois ocorrerá toda vez que você fizer a chamada no futuro. Eu acredito que a resposta de Sajjad Ashraf é aquela em que a maioria das pessoas vai se interessar.
MMMTroy

37

Para Laravel> = 5,2

Use o método -> pluck ()

$roles = DB::table('roles')->pluck('title');

Se você gostaria de recuperar um array contendo os valores de uma única coluna, você pode usar o método de arrancar


Para Laravel <= 5.1

Use o método -> lists ()

$roles = DB::table('roles')->lists('title');

Este método retornará uma matriz de títulos de função. Você também pode especificar uma coluna de chave personalizada para a matriz retornada:


2
Esta não é realmente uma resposta à pergunta (que era especificamente sobre junções / relacionamentos).
ou

30

Você pode fornecer uma matriz de campos no parâmetro get como:

return Response::eloquent(Theme::with('user')->get(array('user.username'));

ATUALIZAÇÃO (para Laravel 5.2) A partir da documentação , você pode fazer o seguinte:

$response = DB::table('themes')
    ->select('themes.*', 'users.username')
    ->join('users', 'users.id', '=', 'themes.user_id')
    ->get();

2
Tentei fazer isso e mostra um erro SQLSTATE[42S22]: Column not founde seu SQL não inclui a tabela no with. O sql que aparece no erro é "SELECT fk_table.column1 FROM main_table".
Michel Ayres

1
É "users.username" (não "user.username"). O código na resposta funcionará se você tiver os nomes das tabelas e colunas correspondentes ao seu banco de dados real. Essa é a desvantagem dessa solução, ela está construindo uma consulta SQL em vez de usar o Eloquent, então os nomes devem corresponder às tabelas e colunas reais do banco de dados.
ou

22

Eu sei, você pede Eloquent, mas você pode fazer isso com o Fluent Query Builder

$data = DB::table('themes')
    ->join('users', 'users.id', '=', 'themes.user_id')
    ->get(array('themes.*', 'users.username'));

16

É assim que eu faço

$posts = Post::with(['category' => function($query){
        $query->select('id', 'name');
      }])->get();

A primeira resposta do usuário 2317976 não funcionou para mim, estou usando o laravel 5.1


2
Resposta atualizada = útil!
thesunneversets de

Obrigado. Isso funciona bem para mim. Devo adicionar a chave estrangeira na instrução select como você fez com 'id', caso contrário, ele retorna nulo.
Iman Sedighi

No entanto, isso ainda recupera um campo "pivô" para cada resultado, contendo ambos os ids (post_id e category_id) certo? Como posso me livrar disso?
mayid,

1
@mayid, você pode tentar adicionar pivot$ array oculto de Post Modelprotected $hidden = ['pivot']
Sajjad Ashraf

Esta é a melhor solução (supondo que você esteja usando uma versão bastante moderna do Laravel)
ou

11

Outra opção é fazer uso da $hiddenpropriedade no modelo para ocultar as colunas que você não deseja exibir. Você pode definir essa propriedade em tempo real ou definir padrões em seu modelo.

public static $hidden = array('password');

Agora, a senha do usuário será ocultada quando você retornar a resposta JSON.

Você também pode configurá-lo em tempo real de maneira semelhante.

User::$hidden = array('password');

2
no Laravel 4.2 estou obtendo 'Não é possível acessar a propriedade protegida User :: $ hidden' quando tento configurar isso dinamicamente.
mtmacdonald

1
não deveria ser static.
StackOverflowed em

@StackOverflowed, suponho que você não percebeu a idade desta pergunta / resposta e que ela se relacionava com o Laravel 3.
Jason Lewis

10

Usando com paginação

$data = DB::table('themes')
->join('users', 'users.id', '=', 'themes.user_id')
->select('themes.*', 'users.username')
->paginate(6);

6

user2317976 introduziu uma ótima maneira estática de selecionar colunas de tabelas relacionadas.

Aqui está um truque dinâmico que descobri para que você possa obter o que quiser ao usar o modelo:

return Response::eloquent(Theme::with(array('user' => function ($q) {
    $q->addSelect(array('id','username'))
}))->get();

Acabei de descobrir que esse truque também funciona bem com load (). Isso é muito conveniente.

$queriedTheme->load(array('user'=>function($q){$q->addSelect(..)});

Certifique-se de incluir também a chave da tabela de destino, caso contrário, ela não será capaz de encontrá-la.


6

Deste jeito:

Post::with(array('user'=>function($query){
    $query->select('id','username');
}))->get();

Sempre explique sua resposta.
Rohit Gupta

Tive um problema parecido, essa é a maneira mais inteligente até agora! Esta resposta é subestimada!
eldblz

Esta é a mesma resposta que já foi enviada anteriormente por Sajjad Ashraf.
ou

5

Eu sei que essa é uma pergunta antiga, mas se você estiver construindo uma API, como o autor da pergunta faz, use transformadores de saída para executar essas tarefas.

Transofrmer é uma camada entre o resultado real da consulta ao banco de dados e um controlador. Ele permite controlar e modificar facilmente o que será enviado a um usuário ou consumidor de API.

Eu recomendo Fractal como uma base sólida de sua camada de transformação de saída. Você pode ler a documentação aqui .



4

No Laravel 5.5, a maneira mais limpa de fazer isso é:

Theme::with('user:userid,name,address')->get()

Você adiciona dois pontos e os campos que deseja selecionar separados por uma vírgula e sem espaço entre eles.


Você sabe como podemos buscar colunas específicas da tabela relacionada ao usar a paginação.
Daniyal Nasir

2

Usando o modelo:

Model::where('column','value')->get(['column1','column2','column3',...]);

Usando o Query Builder:

DB::table('table_name')->where('column','value')->get(['column1','column2','column3',...]);

0

Se bem entendi isso, o que é retornado está bom, exceto que você deseja ver apenas uma coluna. Nesse caso, o seguinte deve ser muito mais simples:

return Response::eloquent(Theme::with('user')->get(['username']));

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.