Tìm hiểu về Collection trong Laravel (Phần 1)
Laravel
20
PHP
74
White

Thành Minh viết ngày 20/07/2017

Collection là gì?

Collection là một class trong Laravel giúp lập trình viên làm việc với mảng dễ dàng hơn, đặc biệt khi thao tác với lượng dữ liệu từ Database vì mặc định trong Laravel kiểu dữ liệu trả về từ Laravel sẽ là Collection.

Một điều đặc biệt nữa là giá trị trong collection sẽ bất biến (immutable), nghĩa là khi ta làm cái khỉ gì với các phương thức của Collection thì nó vẫn sẽ luôn trả về Collection.

Vì số lượng phương thức trong collection rất là nhiều (80 phương thức), nên bài này mình sẽ chia ra thành 3 phần.

Tạo Collection

Việc tạo một collection trong Laravel rất là dễ, như khai báo mảng hay các kiểu khác vậy:

$collection = collect([1, 2, 3]);

Các phương thức trong Collection

Phương thức liệt kê

all()

Phương thức all() sẽ trả về một mảng tương ứng với Collection đó, ví dụ:

$collect([1, 2, 3])->all()

// [1, 2, 3]

average()

Đây là một cái tên khác được đặt ra cho dễ nhớ của phương thức avg()

avg()

Phương thức avg() sẽ trả về giá trị trung bình của các key đã cho, ví dụ:

$idols = collect([
    ['name' => 'Yui Hatano', 'age' => 29],
    ['name' => 'Takizawa Laura', 'age' => 24],
    ['name' => 'Ai Shinozaki', 'age' => 25]
    ])->avg('age');

// 26

Hoặc:

$cum_time = collect([15, 20, 10])->avg();

// 15

chunk()

Phương thức chunk() sẽ chia nhỏ Collection đã cho thành các Collection khác nằm với kích thước đã cho, ví dụ:

$ball_length = collect([1, 2, 3, 4, 5, 6, 7]);

$chunks = $ball_length->chunk(4);

Lúc này $chunks sẽ là một collection chứa 2 collection mới. Ta sẽ thử kiểm tra bằng cách chuyển nó sang một mảng:

$ball_length->toArray();

// [[1, 2, 3, 4], [5, 6, 7]]

collapse()

Phương thức này sẽ gom hết các mảng trong collection thành một mảng:

$collect =  collect([[0, 9, 8], [9, 9, 9], [9, 9, 9, 9]])

$number_phone = $collect->collapse();

$number_phone->all();

// [0, 9, 8, 9, 9, 9, 9, 9, 9, 9]

combine()

Phương thức này sẽ kết hợp Collection và một mảng khác, trong đó mảng trong Collection được coi là key còn mảng thêm vào sẽ là value (key => value):

$collect = collect(['name', 'age']);

$info = $collect->combine(['Doge', 69]);

$info->all();

// ['name' => 'Doge', 'born' => 69]

contains()

Phương thức này sẽ kiểm tra trong Collection xem có giá trị đã cho không:

$long_bi = collect(['age' => 15, 'gender' => '?', 'feedback' => 'cancer']);

$long_bi->contains('cancer');

// true

$long_bi->contains('male');

// false

count()

Cái tên đã nói lên tất cả, phương thức này sẽ trả về số phần tử trong Collection:

$hash = collect(['md5', 'sha1', 'aes']);

$hash->count();

// 3

diff()

Phương thức này sẽ so sánh mảng trong Collection với một mảng khác và trả về một collection chứa các giá trị khác nhau dựa trên value trong 2 mảng:

$collection = collect([1, 2, 3, 4, 5]);

$diff = $collection->diff([2, 4, 6, 8]);

$diff->all();

// [1, 3, 5]

diffKeys()

Phương thức này cũng giống phương thức diff() ở trên, nhưng thay vì so sánh value, nó sẽ so sánh các key với nhau:

$collection = collect([
    'one' => 10,
    'two' => 20,
    'three' => 30,
    'four' => 40,
    'five' => 50,
]);

$diff = $collection->diffKeys([
    'two' => 2,
    'four' => 4,
    'six' => 6,
    'eight' => 8,
]);

$diff->all();

// ['one' => 10, 'three' => 30, 'five' => 50]

each()

Phương thức này cũng gần gần giống cái forEach củ chuối trong JavaScript vậy, nó sẽ lặp qua từng phần tử trong collection và đưa nó vào callback

$collection = $collection->each(function ($item, $key) {
    //
});

Nếu đang lặp mà muốn dừng lại thì chỉ cần return một phát là xong:

$collection = $collection->each(function ($item, $key) {
    if (/* some condition */) {
        return false;
    }
});

every()

Phương thức này sẽ lặp qua tất cả các phần tử trong collection và kiểm tra điều kiện đã cho,
nếu tất cả đều đúng thì sẽ trả về true,còn sai một cái thì sẽ trả về false

collect([1, 2, 3, 4])->every(function ($value, $key) {
    return $value > 2;
});

// false

except()

Phương thức này sẽ loại trừ các phần tử dựa trên key được cho từ một collection và trả về một collection mới:

$collection = collect(['product_id' => 1, 'price' => 100, 'discount' => false]);

$filtered = $collection->except(['price', 'discount']);

$filtered->all();

// ['product_id' => 1]

filter()

Phương thức này hao hao every() một tí, nhưng thay vì trả về true hoặc false, nó sẽ trả về các phần tử đúng với điều kiện đã cho:

$collection = collect([1, 2, 3, null, false, '', 0, []]);

$collection->filter()->all();

// [1, 2, 3]

first()

Phương thức này giống với filter() nhưng thay vì nó trả về tất cả các phần tử thì nó sẽ trả về phần tử đầu tiên :

collect([1, 2, 3, 4])->first(function ($value, $key) {
    return $value > 2;
});

// 3

Điều khá thú vị là nếu gọi phương thức này mà không có argument nào thì nó sẽ trả về phần tử đầu tiên trong collection:

collect([1, 2, 3, 4])->first();

// 1

flatMap()

Cũng như các phương thức trên, nhưng phương thức flatMap() có thể tự do sửa đổi hay làm bất cứ thứ gì và trả về một collection mới:

$collection = collect([
    ['name' => 'Sally'],
    ['school' => 'Arkansas'],
    ['age' => 28]
]);

$flattened = $collection->flatMap(function ($values) {
    return array_map('strtoupper', $values);
});

$flattened->all();

// ['name' => 'SALLY', 'school' => 'ARKANSAS', 'age' => '28'];

flatten()

Trong mảng đa chiều, phương thức này sẽ trả về tất cả value và loại bỏ key trong mảng đó và trở thành mảng 1 chiều:

$collection = collect(['name' => 'taylor', 'languages' => ['php', 'javascript']]);

$flattened = $collection->flatten();

$flattened->all();

// ['taylor', 'php', 'javascript'];

Tuy nhiên bạn cũng có thể loại bỏ dựa theo các lớp mà bạn cần, có vẻ khá khó hiểu thì xem ví dụ sau:

$collection = collect([
    'Apple' => [
        ['name' => 'iPhone 6S', 'brand' => 'Apple'],
    ],
    'Samsung' => [
        ['name' => 'Galaxy S7', 'brand' => 'Samsung']
    ],
]);

$products = $collection->flatten(1);

$products->values()->all();

/*
    [
        ['name' => 'iPhone 6S', 'brand' => 'Apple'],
        ['name' => 'Galaxy S7', 'brand' => 'Samsung'],
    ]
*/

Như trong ví dụ trên thì mình gán một argument là 1, điều này có nghĩa là mình sẽ bỏ đi các key ở lớp ngoài cũng, nếu như mình cho nó là 2 thì nó sẽ bỏ lớp tiếp theo, lúc đó nó sẽ còn:

/*
    [
        ['iPhone 6S',  'Apple'],
        ['Galaxy S7', 'Samsung'],
    ]
*/

flip()

Phương thức này sẽ hoán đổi các keyvalue tương ứng với nhau, ví dụ:

$collection = collect(['name' => 'taylor', 'framework' => 'laravel']);

$flipped = $collection->flip();

$flipped->all();

// ['taylor' => 'name', 'laravel' => 'framework']

forget()

Phương thức này sẽ bỏ đi trực tiếp một phần tử trong collection dựa trên key của phần tử đó:

$collection = collect(['name' => 'taylor', 'framework' => 'laravel']);

$collection->forget('name');

$collection->all();

// ['framework' => 'laravel']

forPage()

Phương thức này trả về một collection mới chứa các phần tử có thể có mặt trên một số trang nhất định. Phương thức chấp nhận số trang là argument đầu tiên của nó và số lượng các phần tử để hiển thị trên mỗi trang là argument thứ hai được đưa vào của nó (cái này hơi khó hiểu xíu):

$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9]);

$chunk = $collection->forPage(2, 3);

$chunk->all();

// [4, 5, 6]

get()

Phương thức này sẽ trả về phần tử dựa vào key đã cho. Nếu như key không tồn tại thì sẽ trả về null:

$collection = collect(['name' => 'taylor', 'framework' => 'laravel']);

$value = $collection->get('name');

// taylor

Ta có thể thêm giá trị mặc định bằng cách cho vào argument thứ 2 :

$collection = collect(['name' => 'taylor', 'framework' => 'laravel']);

$value = $collection->get('name');

// taylor

Hoặc thậm chí là callback:

$collection->get('email', function () {
    return 'default-value';
});

// default-value

Nếu như key không xác định thì callback sẽ được trả về.

groupBy()

Phương thức này sẽ nhóm các mảng trong collection lại dựa trên value tương ứng với key được truyền vào:

$collection = collect([
    ['account_id' => 'account-x10', 'product' => 'Chair'],
    ['account_id' => 'account-x10', 'product' => 'Bookcase'],
    ['account_id' => 'account-x11', 'product' => 'Desk'],
]);

$grouped = $collection->groupBy('account_id');

$grouped->toArray();

/*
    [
        'account-x10' => [
            ['account_id' => 'account-x10', 'product' => 'Chair'],
            ['account_id' => 'account-x10', 'product' => 'Bookcase'],
        ],
        'account-x11' => [
            ['account_id' => 'account-x11', 'product' => 'Desk'],
        ],
    ]
*/

Ngoài việc đưa key vào, bạn có thể dùng callback, nó sẽ trả về giá trị mà bạn đặt cho key khi nhóm các mảng lại:

$grouped = $collection->groupBy(function ($item, $key) {
    return substr($item['account_id'], -3);
});

$grouped->toArray();

/*
    [
        'x10' => [
            ['account_id' => 'account-x10', 'product' => 'Chair'],
            ['account_id' => 'account-x10', 'product' => 'Bookcase'],
        ],
        'x11' => [
            ['account_id' => 'account-x11', 'product' => 'Desk'],
        ],
    ]
*/

has()

Phương thức này sẽ kiểm tra xem key truyền vào có tồn tại hay không:

$collection = collect(['account_id' => 1, 'product' => 'Desk']);

$collection->has('product');

// true

implode()

Phương thức này sẽ ghép value dựa trên key (argument thứ nhất) và kí tự nối lại là argument thứ 2:

$collection = collect([
    ['account_id' => 1, 'product' => 'Desk'],
    ['account_id' => 2, 'product' => 'Chair'],
]);

$collection->implode('product', ', ');

// Desk, Chair

Nếu collection chỉ bao gồm mảng một chiều gồm chuỗi hoặc số thì ta không cần truyền key vào mà chỉ cần truyền kí tự nối lại thôi:

collect([1, 2, 3, 4, 5])->implode('-');

// '1-2-3-4-5'

intersect()

Phương thức này sẽ so sánh collection gốc và một mảng được truyền vào, rồi loại bỏ tất cả các phần tử không tồn tại trong collection gốc, sau đó trả về một collection mới:

$collection = collect(['Desk', 'Sofa', 'Chair']);

$intersect = $collection->intersect(['Desk', 'Chair', 'Bookcase']);

$intersect->all();

// [0 => 'Desk', 2 => 'Chair']

isEmpty()

Cái tên đã nói lên tất cả, phương thức này sẽ trả về true nếu collection rỗng và false nếu ngược lại

isNotEmpty()

Ngược lại với isEmpty()

Tổng kết

Có thể thấy Collections trong Laravel giúp chúng ta tiết kiệm được rất nhiều thời gian làm việc, trên đây là gần 30 trong Laravel trong 80 phương thức của Collections, các phương thức khác mình sẽ giới thiệu trong các phần sau.

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Thành Minh

7 bài viết.
37 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
28 20
1. Các thư viện cần dùng Thư viện (Link) để xử lí file Zip. Thư viện (Link) để xử lí file Rar. Thư viện (Link), thư viện rarfile bắt buộc đi kèm v...
Thành Minh viết 9 tháng trước
28 20
White
18 3
V8 hay còn gọi là Chrome V8, là một Javascript engine được phát triển bởi Chromium Project, mục đích ban đầu là dành cho Google Chrome nói riêng và...
Thành Minh viết 2 tháng trước
18 3
White
7 2
Mỗi năm thì lại có một bản ECMAScript được thêm vào, cùng với đó là thêm kha khá tính năng mới, bài viết này sẽ kể đến một vài tính năng nhỏ nhưng ...
Thành Minh viết 29 ngày trước
7 2
Bài viết liên quan
White
2 2
Bash script to fast serve Laravel project Lười gõ dòng lệnh quá nên tạo ra cái script để gõ nhanh :D laravelstart.sh /bin/bash if z "$1" ] ...
Vũ Hoàng Chung viết 11 tháng trước
2 2
White
8 0
Giới thiệu Việc dùng shortname để thay cho emoticon thật không xa lạ gì với mọi người. Chẳng hạn ngay trong Kipaplog, khi bạn gõ :joy: thì bài viết...
Cùi Bắp viết gần 2 năm trước
8 0
White
24 8
Hi cả nhà, đây là bài viết đầu tiên của mình trên Kipalog nên có gì không hay mong các bạn thông cảm :D Realtime là gì ? Như chúng ta đều đã biế...
Nguyễn Thế Huy viết 4 tháng trước
24 8
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
7 bài viết.
37 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!