Dapatkan Kolom Tertentu Menggunakan Fungsi "With ()" di Laravel Eloquent

196

Saya punya dua meja, Userdan Post. Seseorang Userdapat memiliki banyak postsdan satu postmilik hanya satu user.

Dalam Usermodel saya, saya memiliki hasManyhubungan ...

public function post(){
    return $this->hasmany('post');
}

Dan dalam postmodel saya, saya memiliki belongsTohubungan ...

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

Sekarang saya ingin bergabung dengan dua tabel ini menggunakan Eloquent with()tetapi ingin kolom khusus dari tabel kedua. Saya tahu saya bisa menggunakan Pembuat Kueri tetapi saya tidak mau.

Ketika dalam Postmodel saya menulis ...

public function getAllPosts() {
    return Post::with('user')->get();
}

Ini menjalankan kueri berikut ...

select * from `posts`
select * from `users` where `users`.`id` in (<1>, <2>)

Tapi yang saya inginkan adalah ...

select * from `posts`
select id,username from `users` where `users`.`id` in (<1>, <2>)

Ketika saya menggunakan ...

Post::with('user')->get(array('columns'....));

Itu hanya mengembalikan kolom dari tabel pertama. Saya ingin menggunakan kolom spesifik with()dari tabel kedua. Bagaimana saya bisa melakukan itu?

Awais Qarni
sumber

Jawaban:

346

Yah saya menemukan solusinya. Hal ini dapat dilakukan dengan melewatkan closurefungsi with()seperti indeks array kedua

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

Itu hanya akan memilih iddan usernamedari tabel lain. Saya harap ini akan membantu orang lain.


Ingat bahwa kunci utama (id dalam kasus ini) harus menjadi param pertama dalam $ query-> select () untuk benar-benar mengambil hasil yang diperlukan. *

Awais Qarni
sumber
1
Aneh, saya tidak bisa melakukan ini. Segera setelah saya menambahkan $query->select('id','username');, saya mulaiTrying to get property of non-object
user1669496
5
Aneh! masih mengembalikan semua bidang pengguna. @AwaisQarni
justin
2
Terima kasih telah berbagi ini. Di mana Anda menemukan kemungkinan ini? Saya tidak menemukan ini di dokumen Laravel.
Symen Timmermans
80
Bagi mereka yang melihat ini, ingat bahwa kunci utama ( iddalam hal ini) diperlukan dalam $query->select()untuk benar-benar mengambil hasil yang diperlukan. Saya menghilangkan ini dalam kode saya dan tidak tahu mengapa tidak menemukan hasil. Saya konyol! Semoga ini bisa membantu orang lain dengan masalah yang sama
Azirius
4
hebat, hanya perlu menambahkan kunci asing, di sini post_id nya jika tidak hasilnya akan kosong. Menyebutkan kunci Asing penting di sini. Terima kasih :)
Hashaam Ahmed
102

Anda dapat melakukannya seperti ini sejak Laravel 5.5:

Post::with('user:id,username')->get();

Peduli idbidang dan foreign keyssebagaimana dinyatakan dalam dokumen :

Saat menggunakan fitur ini, Anda harus selalu menyertakan kolom id dan kolom kunci asing apa pun yang relevan dalam daftar kolom yang ingin Anda ambil.

Misalnya, jika pengguna milik tim dan memiliki team_idsebagai kunci kolom asing, maka $post->user->teamkosong jika Anda tidak menentukan team_id

Post::with('user:id,username,team_id')->get();
Adam
sumber
13
Jangan lupa untuk memasukkan kunci asing (dengan asumsi post_id di sini) untuk menyelesaikan hubungan, jika tidak, Anda akan mendapatkan hasil kosong untuk relasi Anda.
Hashaam Ahmed
2
Ini benar-benar jawaban yang dipilih. Bekerja seperti pesona :)
Graham
@ Adam, Ini akan membatasi kolom di tabel anak, bagaimana saya bisa membatasi kolom dari tabel Tabel induk bersama dengan tabel anak?
Sodium
@GauravGenius semua yang Anda ingin batasi dari parant belogns dalam get()metode iniPost::with('user:id,username')->get(['age', 'color']);
Adam
82

Dalam Postmodel Anda

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

Kredit asli diberikan ke Laravel Eager Loading - Hanya memuat kolom tertentu

pengguna1669496
sumber
14
Tetapi hubungan ini akan membuatnya seperti hardcode. Dalam semua kondisi itu akan selalu mengembalikan saya dua bidang ini. Mungkin saja saya membutuhkan lebih banyak bidang dalam beberapa situasi lain
Awais Qarni
Maka Anda harus menggunakan pembuat kueri.
user1669496
5
Ini harus menjadi jawaban yang diterima. Ini cara yang benar untuk melakukannya.
BugHunterUK
1
Apakah ada cara untuk melakukan ini dalam versi Laravel 5.3? Saya pikir mereka mengubahnya ... lagi .... dan sekarang mengembalikan nol ketika saya mencoba dengan pendekatan ini
Andre F.
Sudah lama, tetapi Anda bisa menambahkan $fieldsparameter.
JordyvD
69

Ketika pergi ke arah lain (hasMany):

User::with(array('post'=>function($query){
    $query->select('id','user_id');
}))->get();

Jangan lupa untuk memasukkan kunci asing (dengan asumsi itu adalah user_id dalam contoh ini) untuk menyelesaikan hubungan, jika tidak Anda akan mendapatkan hasil nol untuk hubungan Anda.

Terima kasih
sumber
6
Ya, persis, "Jangan lupa untuk memasukkan kunci asing (dengan asumsi itu adalah user_id dalam contoh ini)"
aqingsao
Anda harus memasukkan kolom yang mendefinisikan hubungan Anda di bidang tertentu, dalam hal ini user_id
alimfazeli
Kakak yang bagus.
Shahrukh Anwar
ya ampun, penggunaan kunci asing itu sangat penting, beruntung saya melihat ans Anda kalau tidak saya akan menggaruk kepala saya selama berjam-jam lol. Terima kasih sobat!
Hashaam Ahmed
34

Di Laravel 5.7 Anda dapat memanggil bidang tertentu seperti ini

$users = App\Book::with('author:id,name')->get();

Penting untuk menambahkan foreign_keybidang dalam pemilihan.

hendra1
sumber
11
jangan lupa untuk menambahkan bidang kunci asing
hendra1
2
Jangan lupa untuk memperhatikan komentar @ hendra1, semua bidang kunci asing juga diperlukan bersama dengan kunci utama, jika tidak, Anda akan mendapatkan koleksi kosong. Bung menghemat waktu saya. Terima kasih
Rajesh Vishnani
14

Dalam Postmodel Anda :

public function userWithName()
{
    return $this->belongsTo('User')->select(array('id', 'first_name', 'last_name'));
}

Sekarang kamu bisa menggunakannya $post->userWithName

Duy Hoang
sumber
2
Betulkah? Bagi saya ini hanya mengembalikan apa-apa, yaitu rusak?
Sjwdavies
12

Jika Anda ingin mendapatkan kolom khusus menggunakan with()laravel fasih maka Anda dapat menggunakan kode seperti di bawah ini yang semula dijawab oleh @Adam dalam jawabannya di sini sebagai tanggapan atas pertanyaan yang sama:

Post::with('user:id,username')->get();

Jadi saya telah menggunakannya dalam kode saya tetapi itu memberi saya kesalahan 1052: Column 'id' in field list is ambiguous, jadi jika kalian juga menghadapi masalah yang sama

Maka untuk menyelesaikannya Anda harus menentukan nama tabel sebelum kolom id dalam with()metode seperti kode di bawah ini :

Post::with('user:user.id,username')->get();
Haritsinh Gohil
sumber
Ini mengembalikan nol untuk saya tetapi saya tidak tahu ini mungkin sebelumnya! Ok, jadi saya memposting prematurley tetapi saya menemukan hasilnya. Untuk menggunakan metode ini (terlihat jauh lebih bersih) Anda harus menyertakan tautan hubungan, misalnya kolom ID saat menarik data dengan. Tanpa specifier ini, Anda mendapatkan pengembalian nol.
Adsy2010
yeah @ Adsy2010, untuk mendapatkan data hubungan terkait Anda juga harus mendapatkan kolom id atau kunci utama atau id mana pun yang bertanggung jawab atas hubungan itu.
Haritsinh Gohil
10

Saya menemukan masalah ini tetapi dengan lapisan kedua benda terkait. @Awais Qarni menjawab dengan memasukkan kunci asing yang sesuai dalam pernyataan pilih bersarang. Sama seperti id diperlukan dalam pernyataan pilih bersarang pertama untuk referensi model terkait, kunci asing diperlukan untuk referensi tingkat kedua model terkait; dalam contoh ini model Perusahaan.

Post::with(['user' => function ($query) {
        $query->select('id','company_id', 'username');
    }, 'user.company' => function ($query) {
        $query->select('id', 'name');
    }])->get();

Selain itu, jika Anda ingin memilih kolom tertentu dari model Post, Anda harus menyertakan kolom user_id dalam pernyataan pilih untuk referensi.

Post::with(['user' => function ($query) {
        $query->select('id', 'username');
    }])
    ->select('title', 'content', 'user_id')
    ->get();
jwarshaw
sumber
4

Perhatikan bahwa jika Anda hanya perlu satu kolom dari tabel maka menggunakan 'daftar' cukup bagus. Dalam kasus saya, saya mengambil artikel favorit pengguna tetapi saya hanya ingin artikel id:

$favourites = $user->favourites->lists('id');

Mengembalikan array id, misalnya:

Array
(
    [0] => 3
    [1] => 7
    [2] => 8
)
omar j
sumber
itu mengembalikan koleksi!
Giovanni Far
jika Anda menginginkan array maka panggil toArray()!!! $user->favourites->lists('id')->toArray();
Giovanni Far
Kueri masih akan mendapatkan kolom lain karena metode list () hanya mengubah array hasil, jadi jika Anda hanya perlu 'id' dari tabel itu, Anda mungkin ingin menentukannya dalam kueri. Itu selalu merupakan kebiasaan yang baik untuk menjaga kinerja dalam pikiran ketika melakukan permintaan. Nikmati pengkodean!
Ervin Llojku
-1 $user->favouritesakan dikembalikan Collectiondengan semua bidang yang dipilih. Penggunaan yang benar adalah: $user->favourites()->lists('id').
Wallace Maxters
Memilih semuanya untuk kemudian menggunakan pemfilteran PHP adalah ide yang buruk. Cara terbaik adalah hanya menggunakan bidang yang dibutuhkan di Query. Penting untuk mengetahui perbedaan antara Query\Builder::listsmetode dan Collection::listsmetode.
Wallace Maxters
1

Anda juga dapat menentukan kolom pada model terkait pada saat mengaksesnya.

Post::first()->user()->get(['columns....']);

Shreyansh Panchal
sumber
0

Sekarang Anda dapat menggunakan pluckmetode ini pada Collectioncontoh:

Ini hanya akan mengembalikan uuidatributPost model

App\Models\User::find(2)->posts->pluck('uuid')
=> Illuminate\Support\Collection {#983
     all: [
       "1",
       "2",
       "3",
     ],
   }
Giovanni Far
sumber
0

Coba dengan ketentuan.

$id = 1;
Post::with(array('user'=>function($query) use ($id){
    $query->where('id','=',$id);
    $query->select('id','username');
}))->get();
Shirjeel Ahmed Khan
sumber
-3
EmployeeGatePassStatus::with('user:id,name')->get();
Kush
sumber
1
Ini adalah sintaks yang sama seperti dalam jawaban ini (hanya nama yang berbeda untuk model dan kolom)
barbsan