Laravel Eloquent: Cách chỉ lấy một số cột nhất định từ các bảng đã tham gia


102

Tôi có 2 bảng tham gia trong Eloquent là chủ đề và người dùng.

mô hình chủ đề:

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

mô hình người dùng:

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

Cuộc gọi api Eloquent của tôi trông như sau:

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

Nó trả về tất cả các cột từ chủ đề (điều đó tốt) và tất cả các cột từ người dùng (không ổn). Tôi chỉ cần cột 'tên người dùng' từ mô hình người dùng, làm cách nào để giới hạn truy vấn đến đó?


Tôi đang thực hiện tác vụ tương tự, tôi có thể biết liệu tôi đang sử dụng Responseloại lớp nào mà tôi cần nhập không?
Agnes Palit

Câu trả lời:


103

Thay đổi mô hình của bạn để chỉ định những cột bạn muốn chọn:

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

Và đừng quên bao gồm cột bạn đang tham gia.


6
câu trả lời tuyệt vời, cũng như mẹo về việc bao gồm cột tham gia đã giúp tôi tiết kiệm rất nhiều thời gian!
greatwitenorth

Điều gì xảy ra nếu ở một số nơi tôi chỉ cần id thay vì cả id và tên người dùng? Vẫn phải chọn cả hai?
Darius.V

Xin chào, chức năng chọn có cùng chức năng trong trình tạo truy vấn mô hình không?
Gokigooooks

4
Tôi không nghĩ rằng đó là một cách tiếp cận tốt. Nó sẽ là một loại mã hóa khó các tên cột. Tất cả các vị trí sẽ chỉ trả về các cột này. Trong một số api khác, tôi có thể cần thêm một số cột để không hoạt động ở đây. Tôi nghĩ rằng sử dụng QueryBuilder là tùy chọn ở đây.
Aman Sura

2
Đây là một cách tiếp cận ấn tượng vì nó sẽ xảy ra mỗi khi bạn thực hiện cuộc gọi về sau. Tôi tin rằng câu trả lời của Sajjad Ashraf là câu trả lời mà hầu hết mọi người sẽ quan tâm.
MMMTroy

37

Đối với Laravel> = 5.2

Sử dụng -> nhổ () phương pháp

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

Nếu bạn muốn truy xuất một mảng chứa các giá trị của một cột duy nhất, bạn có thể sử dụng phương pháp pluck


Đối với Laravel <= 5.1

Sử dụng -> danh sách () phương pháp

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

Phương thức này sẽ trả về một mảng các tiêu đề vai trò. Bạn cũng có thể chỉ định một cột khóa tùy chỉnh cho mảng được trả về:


2
Đây thực sự không phải là một câu trả lời cho câu hỏi (đặc biệt là về liên kết / mối quan hệ).
orrd

30

Bạn có thể cung cấp một mảng các trường trong tham số get như sau:

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

CẬP NHẬT (cho Laravel 5.2) Từ tài liệu , bạn có thể thực hiện việc này:

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

2
Tôi đã thử điều này và nó hiển thị lỗi SQLSTATE[42S22]: Column not foundvà nó là SQL không bao gồm bảng trong with. Sql mà nó xuất hiện trên lỗi là "SELECT fk_table.column1 FROM main_table".
Michel Ayres

1
Đó là "users.username" (không phải "user.username"). Mã trong câu trả lời sẽ hoạt động nếu bạn có tên bảng và cột khớp với cơ sở dữ liệu thực tế của mình. Đó là nhược điểm của giải pháp này, đó là xây dựng một truy vấn SQL thay vì sử dụng Eloquent, vì vậy các tên phải khớp với các bảng và cột cơ sở dữ liệu thực tế của bạn.
orrd

22

Tôi biết, bạn yêu cầu Eloquent nhưng bạn có thể làm điều đó với Fluent Query Builder

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

16

Đây là cách tôi làm điều đó

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

Câu trả lời đầu tiên của user2317976 không phù hợp với tôi, tôi đang sử dụng laravel 5.1


2
Câu trả lời cập nhật = hữu ích!
thesunneversets

Cảm ơn. Việc này ổn với tôi. Tôi phải thêm khóa ngoại vào câu lệnh select như bạn đã làm với 'id' nếu không nó trả về null.
Iman Sedighi

Tuy nhiên, điều này vẫn lấy ra một trường "pivot" cho mỗi kết quả, chứa cả id (post_id và category_id) phải không? Làm thế nào tôi có thể đi xe của nó?
mayid

1
@mayid bạn có thể thử thêm pivotđến $ mảng ẩn Bưu Mẫuprotected $hidden = ['pivot']
Sajjad Ashraf

Đây là giải pháp tốt nhất (giả sử bạn đang sử dụng một phiên bản khá hiện đại của Laravel)
orrd

11

Một tùy chọn khác là sử dụng thuộc $hiddentính trên mô hình để ẩn các cột bạn không muốn hiển thị. Bạn có thể xác định thuộc tính này một cách nhanh chóng hoặc đặt các giá trị mặc định trên mô hình của bạn.

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

Bây giờ mật khẩu người dùng sẽ bị ẩn khi bạn trả lại phản hồi JSON.

Bạn cũng có thể thiết lập nó một cách nhanh chóng theo cách tương tự.

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

2
trong Laravel 4.2, tôi nhận được thông báo 'Không thể truy cập thuộc tính được bảo vệ Người dùng :: $ hidden' khi cố gắng đặt động điều này.
mtmacdonald

1
không nên đâu static.
StackOverflowed

@StackOverflowed, tôi hiểu là bạn không nhận thấy câu hỏi / câu trả lời này bao nhiêu tuổi và nó có liên quan đến Laravel 3.
Jason Lewis

10

Sử dụng với phân trang

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

6

user2317976 đã giới thiệu một cách tĩnh tuyệt vời để chọn các cột của bảng có liên quan.

Đây là một thủ thuật động mà tôi đã tìm thấy để bạn có thể có được bất cứ thứ gì bạn muốn khi sử dụng mô hình:

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

Tôi chỉ thấy thủ thuật này cũng hoạt động tốt với load (). Điều này rất thuận tiện.

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

Đảm bảo rằng bạn cũng bao gồm khóa của bảng mục tiêu nếu không sẽ không thể tìm thấy nó.


6

Cách này:

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

Hãy luôn giải thích câu trả lời của bạn.
Rohit Gupta

Gặp sự cố tương tự, đây là cách thông minh nhất cho đến nay! Câu trả lời này được đánh giá thấp!
Elderblz

Điều này cũng giống như câu trả lời đã được gửi trước đó bởi Sajjad Ashraf.
orrd

5

Tôi biết rằng đây là một câu hỏi cũ, nhưng nếu bạn đang xây dựng một API, như tác giả của câu hỏi, hãy sử dụng máy biến áp đầu ra để thực hiện các tác vụ như vậy.

Transofrmer là một lớp giữa kết quả truy vấn cơ sở dữ liệu thực tế của bạn và một bộ điều khiển. Nó cho phép dễ dàng kiểm soát và sửa đổi những gì sẽ được xuất cho người dùng hoặc người tiêu dùng API.

Tôi đề xuất Fractal như một nền tảng vững chắc cho lớp chuyển đổi đầu ra của bạn. Bạn có thể đọc tài liệu tại đây .



4

Trên Laravel 5.5, cách tốt nhất để làm điều này là:

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

Bạn thêm dấu hai chấm và các trường bạn muốn chọn được phân tách bằng dấu phẩy và không có khoảng cách giữa chúng.


Bạn có biết làm thế nào chúng tôi có thể tìm nạp cột cụ thể của bảng liên quan khi sử dụng phân trang.
Daniyal Nasir

2

Sử dụng mô hình:

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

Sử dụng Trình tạo truy vấn:

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

0

Nếu tôi hiểu rõ điều này, những gì được trả lại là tốt, ngoại trừ bạn chỉ muốn xem một cột. Nếu vậy, điều này bên dưới sẽ đơn giản hơn nhiều:

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.