07/09/2018, 17:20

Những method thông dụng của Collection trong Laravel, bạn đã sử dụng hết chưa?

Khi sử dụng Eloquent của Laravel, lúc ta truy vấn trả về một danh sách bản ghi, thì chúng là tập hợp của các Object Eloquent, và đó chính là Collection. Trong Laravel, có một Object chuyên để xử lý Collection đó là IlluminateSupportCollection (source code), ở ví dụ trên thì đó là ...

Khi sử dụng Eloquent của Laravel, lúc ta truy vấn trả về một danh sách bản ghi, thì chúng là tập hợp của các Object Eloquent, và đó chính là Collection.
Trong Laravel, có một Object chuyên để xử lý Collection đó là IlluminateSupportCollection (source code), ở ví dụ trên thì đó là IlluminateDatabaseEloquentCollection (source code), chúng ta sẽ gọi là Eloquent Collection để phân biệt với Laravel Collection, và chúng được extend từ IlluminateSupportCollection nên chúng có các method cơ bản của Laravel Collection. Tất nhiên Eloquent Collection thì chúng được xây dựng để xử lý thêm một số tác vụ liên quan đến Eloquent, và bài viết này sẽ nhắc đến các method hay được sử dụng, nó sẽ giúp ta giảm được rất nhiều thời gian nếu bạn tận dụng tốt chúng.

chunk()

Đây có lẽ là một method khá tiện ích, khi ta muốn nhóm một số lượng bản ghi thành các nhóm nhỏ để thuận tiện cho việc show hoặc xử lý dữ liệu.
Giờ giả sử ta có một table student với Eloquent Student.

$students = Student::take(12)->get(); // Collection { #items: array:12 [] }
// Dữ liệu là Collection gồm 12 Eloquent Student
// giờ bạn muốn nhóm 12 Eloquent này thành 3 nhóm mỗi nhóm 4 Eloquent
$chunkStudents = $students->chunk(4);

Khi đó dữ liệu sẽ trông như thế này, nó sẽ là Collection chứa 3 Collection

Collection {
    #items: array:3 [
        0 => Collection {#499 ▶}
        1 => Collection {#505 ▶}
        2 => Collection {#504 ▶}
    ]
}

Để sử dụng thì ta chỉ cần dùng foreach như bình thường

foreach ($chunkStudents as $chunkStudent) {
    // Do something
    foreach($chunkStudent as $student) {
        //Do something
    }
}

collapse()

Đây là method ngược lại với method chunk(), sau khi tách ra thành các nhóm bản ghi nhỏ thì ta có thể gộp chúng lại thành 1 Collection duy nhất bằng cách sử dụng collapse().

$collapseStudents = $chunkStudents->collapse();

avg(), average()

Đây là hàm giúp ta tính giá trị trung bình của một trường của toàn bộ bản ghi trong Collection.
Ví dụ ta một bảng điểm sinh viên gồm các field: id, student_id, subject_id, point. Giờ bạn muốn tính điểm trung bình của toàn bộ bản ghi này thì đơn giản là sử dụng:

$studentAvgPoint = $students->avg('point');

isEmpty(), isNotEmpty()

$isEmpty = $students->isEmpty();
// Trả về true nếu không có bản ghi nào trong Collection, nếu có thì trả false
$isNotEmpty = $students->isNotEmpty();
// Hàm này ngược với hàm ở trên thôi.

Kiểm tra xem Collection có chứa phần tử nào không

max(), min()

Lấy giá trị lớn nhất của một field nào đó trong bản ghỉ, giả sử ta muốn xem điểm cao nhất và thấp nhất trong số danh sách student thì ta làm như sau.

$pointMax = $students->max('point');
$pointMin = $students->min('point');

count()

Đơn giản là trả về số bản ghi có trong Collection

$studentCount = $students->count();

pluck()

Phuơng thức này khá hữu dụng trong một số trường hợp, dùng để lấy toàn bộ một field nào đó và trả về mảng chứa giá trị của tất cả các field đó. Thông thường mình hay dùng để lấy toàn bộ id có trong bản ghi để dùng trong các điều kiện whereIn.

$studentIds = $students->pluck('id'); //kết quả là 1 Collection chửa mảng các id của student

each()

Đây là cách lặp qua các phần tử của Collection, cũng tương tự như khi ta dùng foreach

$students->each(function($student, $key){
    echo $key, $student->id;
});
// Cũng không khác gì so với ta dùng cách foreach truyền thống.
foreach ($students as $key => $student) {
    echo $key, $student->id;
}

Tuy nhiên thì ta có thể đặt điều kiện để ngắt vòng lặp bằng cách return false

$students->each(function($student, $key){
    if ($student->id > 5) {
        return false; //Khi student có id > 5 thì sẽ dừng vòng lặp
    }
    echo $key, $student->id;
});

every()

Phương thức này trả về kết quả boolean(true/false), bằng cách kiểm tra xem tất cả bản ghi có thỏa mãn điều kiện nào đó hay không?

$pointGreatThanFive = $student->every(function($student, $key){
    return $student->point > 5;
});

Nếu toàn bộ student trong bản ghi trên có point lớn hơn 5 thì trả về true, còn không thì trả về false;

filter()

Ai hay sử dụng Javascript thì sẽ thấy phuơng thức cách sử dụng phương thức này cho Collection cũng hoàn toàn giống nhau, ta sẽ lọc các bản ghi theo một điều kiện nào đó. Giờ giả sử ta chỉ muốn lấy những student có point lớn hơn 5, thì ta sẽ dùng như sau:

$filterStudents = $students->filter(function($student, $key){
    return $student->point > 5;
});

map()

Đây cũng là phương thức tương tự trong Javascript, bạn có thể tạo ra một Collection mới dựa theo Collection cũ với một số thay đổi nào đó;
Ví dụ mình muốn cộng cho mỗi sinh viên 1 điểm thì ta có thể làm như sau:

$newStudents = $students->map(function($student, $key){
    $student->point += 1;
    return $student;
});

$newStudents là Collection mới có point của mỗi student được cộng thêm 1 so với mỗi student trong $students.

first(), last()

Khi bạn chỉ muốn lấy phần từ đầu tiền của Collection, thì ta dùng first(). Ngược lại nếu bạn muốn lấy phần từ cuối cùng thì ta dùng last(). Ngoài ra bạn có thể thêm điều kiện để lấy phần tử cho phù hợp, kết quả trả về 1 Eloquent nếu tìm thấy phần tử đầu tiên thoả mãn, còn không thì trả về null.

$firstStudent = $students->first();// Trả về phần từ đầu tiên của Collection và sẽ là một Eloquent
$firstConditionSutdent = $students->frist(function($student, $key){
    return $student->point == 10; //Trả về student đầu tiên có point = 10 theo thứ tự trong bản ghi
});

toArray(), toJson()

Để chuyển từ dạng Object sang dạng mảng hoặc kiểu dữ liệu Json.

$studentArray = $students->toArray();
$studentJson = $students->toJson();

partition()

Ta dùng khi muốn chia Collection thành 2 phần theo một điều kiện nào đó.
Ví dụ ta muốn tách danh sách students ra thành một bên có point lớn hơn hoặc bằng 5 và bên còn lại có điểm nhỏ hơn 5, ta sẽ làm như sau:

list($greaterEqualFive, $lessFive) = $students->partition(function ($student) {
    return $student->point >= 5;
});

$greaterEqualFive sẽ chứa kết quả các student có điểm lớn hơn bằng 5, còn $lessFive sẽ chứa các student có điểm nhỏ hơn 5.

Collection còn rất nhiều phương thức khác, thế nhưng ở trên mình chỉ liệt kê một số phuơng thức khá tiện ích hay được sử dụng, có thể có phương thức nào đó bạn không để ý và không nghĩ là có thì hy vọng mình cũng đã giúp ích cho bạn nhớ nó để sử dụng. Xin cảm ơn bạn đã đọc bài viết.

0