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?

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. *


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();

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


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.


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.


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


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();

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();

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
)

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....']);


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",
     ],
   }

0

Coba dengan ketentuan.

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

-3
EmployeeGatePassStatus::with('user:id,name')->get();

1
Ini adalah sintaks yang sama seperti dalam jawaban ini (hanya nama yang berbeda untuk model dan kolom)
barbsan
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.