😄Collections full (ok)
https://laravel.com/docs/9.x/collections#creating-collections
Last updated
https://laravel.com/docs/9.x/collections#creating-collections
Last updated
Bài tập 1: Xóa phần tử rỗng khỏi mảng
['taylor', 'abigail', null]
C:\xampp\htdocs\wpclidemo\app\Http\Controllers\HomeController.php
$collection = collect(['taylor', 'abigail', null])->map(function ($name) {
return strtoupper($name);
})->reject(function ($name) {
return empty($name);
});
echo '<pre>';
var_export($collection);
echo '</pre>';
die(" ");
Bài 2.1 : Extending Collections
C:\xampp\htdocs\wpclidemo\app\Http\Controllers\HomeController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
class HomeController extends Controller {
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct() {
$this->middleware('auth');
}
/**
* Show the application dashboard.
*
* @return \Illuminate\Contracts\Support\Renderable
*/
public function index() {
return view('home');
}
/**
* Show the application dashboard.
*
* @return \Illuminate\Contracts\Support\Renderable
*/
public function show() {
Collection::macro('toUpper', function () {
return $this->map(function ($value) {
return Str::upper($value);
});
});
$collection = collect(['first', 'second']);
$upper = $collection->toUpper();
echo '<pre>';
var_export($upper);
echo '</pre>';
die(" ");
$products = "";
return view('welcome')->with(compact('products'));
}
}
Bài 2.2 Macro Arguments (Nếu cần, bạn có thể xác định các macro chấp nhận các đối số bổ sung:)
Collection::macro('toLocale', function ($locale) {
return $this->map(function ($value) use ($locale) {
return Lang::get($value, [], $locale);
});
});
$collection = collect(['first', 'second']);
$translated = $collection->toLocale('es');
echo '<pre>';
var_export($translated);
echo '</pre>';
die(" ");
all(
)
$test = collect([1, 2, 3]);
echo '<pre>';
var_export($test->all());
echo '</pre>';
die(" ");
// => Result
array (
0 => 1,
1 => 2,
2 => 3,
)
$average = collect([
['foo' => 10],
['foo' => 10],
['foo' => 20],
['foo' => 40]
]);
echo '<pre>';
var_export($average->avg('foo'));
echo '</pre>';
$products = "";
// Result 20
$collection = collect([1, 2, 3, 4, 5, 6, 7]);
$products = $collection;
echo '<pre>';
var_export($products->chunk(4));
echo '</pre>';
die(" ");
Thực hiện với view 👇
C:\xampp\htdocs\wpclidemo\app\Http\Controllers\HomeController.php
<?php
namespace App\Http\Controllers;
class HomeController extends Controller {
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct() {
$this->middleware('auth');
}
/**
* Show the application dashboard.
*
* @return \Illuminate\Contracts\Support\Renderable
*/
public function index() {
return view('home');
}
/**
* Show the application dashboard.
*
* @return \Illuminate\Contracts\Support\Renderable
*/
public function show() {
$collection = collect([1, 2, 3, 4, 5, 6, 7]);
$products = $collection;
return view('welcome')->with(compact('products'));
}
}
C:\xampp\htdocs\wpclidemo\resources\views\welcome.blade.php
@foreach ($products->chunk(4) as $chunk)
<div class="row">
@foreach ($chunk as $product)
<div class="col-xs-4">{{ $product }}</div>
@endforeach
</div>
@endforeach
collection = collect(str_split('AABBCCCD'));
$chunks = $collection->chunkWhile(function ($value, $key, $chunk) {
return $value === $chunk->last();
});
echo '<pre>';
var_export($chunks->all());
echo '</pre>';
die(" ");
Result 👇
array (
0 =>
Illuminate\Support\Collection::__set_state(array(
'items' =>
array (
0 => 'A',
1 => 'A',
),
'escapeWhenCastingToString' => false,
)),
1 =>
Illuminate\Support\Collection::__set_state(array(
'items' =>
array (
2 => 'B',
3 => 'B',
),
'escapeWhenCastingToString' => false,
)),
2 =>
Illuminate\Support\Collection::__set_state(array(
'items' =>
array (
4 => 'C',
5 => 'C',
6 => 'C',
),
'escapeWhenCastingToString' => false,
)),
3 =>
Illuminate\Support\Collection::__set_state(array(
'items' =>
array (
7 => 'D',
),
'escapeWhenCastingToString' => false,
)),
)
$collection = collect([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]);
$collapsed = $collection->collapse();
echo '<pre>';
var_export($collapsed->all());
echo '</pre>';
die(" ");
Result 👇
array (
0 => 1,
1 => 2,
2 => 3,
3 => 4,
4 => 5,
5 => 6,
6 => 7,
7 => 8,
8 => 9,
)
$collectionA = collect([1, 2, 3]);
$collectionB = $collectionA->collect();
echo '<pre>';
var_export($collectionB->all());
echo '</pre>';
die(" ");
Result 👇
array (
0 => 1,
1 => 2,
2 => 3,
)
$collection = collect(['name', 'age']);
$combined = $collection->combine(['George', 29]);
dd($combined->all());
Result 👇
array (
'name' => 'George',
'age' => 29,
)
$collection = collect(['1 Doe']);
$concatenated = $collection->concat(['2 Doe'])->concat(['name' => '3 Doe']);
echo '<pre>';
var_export($concatenated->all());
echo '</pre>';
die(" ");
Result 👇
array (
0 => '1 Doe',
1 => '2 Doe',
2 => '3 Doe',
)
containsStrict()
This method has the same signature as the contains
method; however, all values are compared using "strict" comparisons.
$collection = collect([1, 2, 3, 4, 5]);
$result = $collection->contains(function ($value, $key) {
return $value > 5;
});
echo '<pre>';
var_export($result);
echo '</pre>';
die(" ");
Result 👇
false
Hoặc
$collection = collect(['name' => 'Desk', 'price' => 100]);
$collection->contains('Desk');
// true
$collection->contains('New York');
// false
die(" ");
Hoặc
$collection = collect([
['product' => 'Desk', 'price' => 200],
['product' => 'Chair', 'price' => 100],
]);
$result = $collection->contains('product', 'Desk');
echo '<pre>';
var_export($result);
echo '</pre>';
die(" ");
Result 👇
true
$collection = collect([1, 2, 3, 4]);
$result = $collection->count();
echo '<pre>';
var_export($result);
echo '</pre>';
die(" ");
Result 👇
4
$collection = collect([1, 2, 2, 2, 3]);
$counted = $collection->countBy();
$counted->all();
// [1 => 1, 2 => 3, 3 => 1]
$collection = collect(['alice@gmail.com', 'bob@yahoo.com', 'carlos@gmail.com']);
$counted = $collection->countBy(function ($email) {
return substr(strrchr($email, "@"), 0);
});
echo '<pre>';
var_export($counted->all());
echo '</pre>';
die(" ");
// ==
array (
'@gmail.com' => 2,
'@yahoo.com' => 1,
)
$collection = collect(['alice@gmail.com', 'bob@yahoo.com', 'carlos@gmail.com']);
$counted = $collection->countBy(function ($email) {
return substr(strrchr($email, "@"), 1);
});
echo '<pre>';
var_export($counted->all());
echo '</pre>';
die(" ");
// ==
array (
'gmail.com' => 2,
'yahoo.com' => 1,
)
$collection = collect([1, 2]);
$matrix = $collection->crossJoin(['a', 'b']);
$matrix->all();
/*
[
[1, 'a'],
[1, 'b'],
[2, 'a'],
[2, 'b'],
]
*/
$collection = collect([1, 2]);
$matrix = $collection->crossJoin(['a', 'b'], ['I', 'II']);
$matrix->all();
/*
[
[1, 'a', 'I'],
[1, 'a', 'II'],
[1, 'b', 'I'],
[1, 'b', 'II'],
[2, 'a', 'I'],
[2, 'a', 'II'],
[2, 'b', 'I'],
[2, 'b', 'II'],
]
*/
$collection = collect([1, 2, 3, 4, 5]);
$diff = $collection->diff([2, 4, 6, 8]);
$diff->all();
// [1, 3, 5]
$collection = collect([
'color' => 'orange',
'type' => 'fruit',
'remain' => 6,
]);
$diff = $collection->diffAssoc([
'color' => 'yellow',
'type' => 'fruit',
'remain' => 3,
'used' => 6,
]);
$diff->all();
// ['color' => 'orange', 'remain' => 6]
$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]
$collection = collect([1, 2, 3, 4, 5]);
$collection->doesntContain(function ($value, $key) {
return $value < 5;
});
// false
duplicatesStrict()
This method has the same signature as the duplicates
method; however, all values are compared using "strict" comparisons.
$collection = collect(['a', 'b', 'a', 'c', 'b']);
$collection->duplicates();
// [2 => 'a', 4 => 'b']
$collection = collect(['a', 'b', 'a', 'c', 'b']);
$result = array();
$collection->each(function ($item, $key) {
echo $item;
});
// abacb
die(" ");
$collection = collect([['John Doe', 35], ['Jane Doe', 33]]);
$collection->eachSpread(function ($name, $age) {
echo $name . " ";
});
// John Doe Jane Doe
die(" ");
collect([1, 2, 3, 4])->every(function ($value, $key) {
return $value > 2;
});
// false
😂
If the collection is empty, the every
method will return true:
$collection = collect([]);
$collection->every(function ($value, $key) {
return $value > 2;
});
// true
$collection = collect(['product_id' => 1, 'price' => 100, 'discount' => false]);
$filtered = $collection->except(['price', 'discount']);
$filtered->all();
// ['product_id' => 1]
$collection = collect([1, 2, 3, 4]);
$filtered = $collection->filter(function ($value, $key) {
return $value > 2;
});
$filtered->all();
// [3, 4]
If no callback is supplied, all entries of the collection that are equivalent to false
will be removed:
$collection = collect([1, 2, 3, null, false, '', 0, []]);
$collection->filter()->all();
// [1, 2, 3]
😒
For the inverse of filter
, see the reject method.
$collection = collect([1, 2, 3, 4]);
$filtered = $collection->reject(function ($value, $key) {
return $value > 2;
});
$filtered->all();
// [1, 2]
collect([1, 2, 3, 4])->first(function ($value, $key) {
return $value > 2;
});
// 3
collect([1, 2, 3, 4])->firstOrFail(function ($value, $key) {
return $value > 5;
});
// Throws ItemNotFoundException...
$collection = collect([
['name' => 'Regena', 'age' => null],
['name' => 'Linda', 'age' => 14],
['name' => 'Diego', 'age' => 23],
['name' => 'Linda', 'age' => 84],
]);
$collection->firstWhere('name', 'Linda');
// ['name' => 'Linda', 'age' => 14]
die(" ");
$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'];
$collection = collect([
'name' => 'taylor',
'languages' => [
'php', 'javascript'
]
]);
$flattened = $collection->flatten();
$flattened->all();
// ['taylor', 'php', 'javascript'];
Hoặc
$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'],
]
*/
$collection = collect(['name' => 'taylor', 'framework' => 'laravel']);
$flipped = $collection->flip();
$flipped->all();
// ['taylor' => 'name', 'laravel' => 'framework']
$collection = collect(['name' => 'taylor', 'framework' => 'laravel']);
$collection->forget('name');
$collection->all();
// ['framework' => 'laravel']
$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9]);
$chunk = $collection->forPage(2, 3);
$chunk->all();
// [4, 5, 6]
Hoặc
$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9]);
$chunk = $collection->forPage(2, 4);
echo '<pre>';
var_export($chunk->all());
echo '</pre>';
// [4, 5, 6,8]
die(" ");
$collection = collect(['name' => 'taylor', 'framework' => 'laravel']);
$value = $collection->get('name');
// taylor
You may optionally pass a default value as the second argument:
$collection = collect(['name' => 'taylor', 'framework' => 'laravel']);
$value = $collection->get('age', 34);
// 34
You may even pass a callback as the method's default value. The result of the callback will be returned if the specified key does not exist:
$collection->get('email', function () {
return 'taylor@example.com';
});
// taylor@example.com
$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->all();
/*
[
'account-x10' => [
['account_id' => 'account-x10', 'product' => 'Chair'],
['account_id' => 'account-x10', 'product' => 'Bookcase'],
],
'account-x11' => [
['account_id' => 'account-x11', 'product' => 'Desk'],
],
]
*/
Hoặc
$grouped = $collection->groupBy(function ($item, $key) {
return substr($item['account_id'], -3);
});
$grouped->all();
/*
[
'x10' => [
['account_id' => 'account-x10', 'product' => 'Chair'],
['account_id' => 'account-x10', 'product' => 'Bookcase'],
],
'x11' => [
['account_id' => 'account-x11', 'product' => 'Desk'],
],
]
*/
Hoặc
Hoặc
$data = new Collection([
10 => ['user' => 1, 'skill' => 1, 'roles' => ['Role_1', 'Role_3']],
20 => ['user' => 2, 'skill' => 1, 'roles' => ['Role_1', 'Role_2']],
30 => ['user' => 3, 'skill' => 2, 'roles' => ['Role_1']],
40 => ['user' => 4, 'skill' => 2, 'roles' => ['Role_2']],
]);
$result = $data->groupBy(['skill', function ($item) {
return $item['roles'];
}], preserveKeys: true);
/*
[
1 => [
'Role_1' => [
10 => ['user' => 1, 'skill' => 1, 'roles' => ['Role_1', 'Role_3']],
20 => ['user' => 2, 'skill' => 1, 'roles' => ['Role_1', 'Role_2']],
],
'Role_2' => [
20 => ['user' => 2, 'skill' => 1, 'roles' => ['Role_1', 'Role_2']],
],
'Role_3' => [
10 => ['user' => 1, 'skill' => 1, 'roles' => ['Role_1', 'Role_3']],
],
],
2 => [
'Role_1' => [
30 => ['user' => 3, 'skill' => 2, 'roles' => ['Role_1']],
],
'Role_2' => [
40 => ['user' => 4, 'skill' => 2, 'roles' => ['Role_2']],
],
],
];
*/
$collection = collect(['account_id' => 1, 'product' => 'Desk', 'amount' => 5]);
$collection->has('product');
// true
$collection->has(['product', 'amount']);
// true
$collection->has(['amount', 'price']);
// false
$collection = collect([
['account_id' => 1, 'product' => 'Desk'],
['account_id' => 2, 'product' => 'Chair'],
]);
$collection->implode('product', ', ');
// Desk, Chair
Hoặc
collect([1, 2, 3, 4, 5])->implode('-');
// '1-2-3-4-5'
$collection = collect(['Desk', 'Sofa', 'Chair']);
$intersect = $collection->intersect(['Desk', 'Chair', 'Bookcase']);
$intersect->all();
// [0 => 'Desk', 2 => 'Chair']
$collection = collect([
'serial' => 'UX301', 'type' => 'screen', 'year' => 2009,
]);
$intersect = $collection->intersectByKeys([
'reference' => 'UX404', 'type' => 'tab', 'year' => 2011,
]);
$intersect->all();
// ['type' => 'screen', 'year' => 2009]
collect([])->isEmpty();
// true
collect([])->isNotEmpty();
// false
collect(['a', 'b', 'c'])->join(', '); // 'a, b, c'
collect(['a', 'b', 'c'])->join(', ', ', and '); // 'a, b, and c'
collect(['a', 'b'])->join(', ', ' and '); // 'a and b'
collect(['a'])->join(', ', ' and '); // 'a'
collect([])->join(', ', ' and '); // ''
$collection = collect([
['product_id' => 'prod-100', 'name' => 'Desk'],
['product_id' => 'prod-200', 'name' => 'Chair'],
]);
$keyed = $collection->keyBy('product_id');
$keyed->all();
/*
[
'prod-100' => ['product_id' => 'prod-100', 'name' => 'Desk'],
'prod-200' => ['product_id' => 'prod-200', 'name' => 'Chair'],
]
*/
Hoặc
$collection = collect([
['product_id' => 'prod-100', 'name' => 'Desk'],
['product_id' => 'prod-200', 'name' => 'Chair'],
]);
$keyed = $collection->keyBy(function ($item) {
return strtoupper($item['product_id']);
});
$keyed->all();
/*
[
'PROD-100' => ['product_id' => 'prod-100', 'name' => 'Desk'],
'PROD-200' => ['product_id' => 'prod-200', 'name' => 'Chair'],
]
*/
$collection = collect([
'prod-100' => ['product_id' => 'prod-100', 'name' => 'Desk'],
'prod-200' => ['product_id' => 'prod-200', 'name' => 'Chair'],
]);
$keys = $collection->keys();
$keys->all();
// ['prod-100', 'prod-200']
collect([1, 2, 3, 4])->last(function ($value, $key) {
return $value < 3;
});
// 2
You may also call the last
method with no arguments to get the last element in the collection. If the collection is empty, null
is returned:
collect([1, 2, 3, 4])->last();
// 4
$lazyCollection = collect([1, 2, 3, 4])->lazy();
get_class($lazyCollection);
// Illuminate\Support\LazyCollection
echo '<pre>';
var_export($lazyCollection->all());
echo '</pre>';
// array ( 0 => 1, 1 => 2, 2 => 3, 3 => 4, )
die(" ");
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
Collection::macro('toUpper', function () {
return $this->map(function ($value) {
return Str::upper($value);
});
});
$collection = collect(['first', 'second']);
$upper = $collection->toUpper();
// ['FIRST', 'SECOND']
$collection = collect([1, 2, 3]);
$collection = collect([1, 2, 3, 4, 5]);
$multiplied = $collection->map(function ($item, $key) {
return $item * 2;
});
$multiplied->all();
// [2, 4, 6, 8, 10]
class Currency
{
/**
* Create a new currency instance.
*
* @param string $code
* @return void
*/
function __construct(string $code)
{
$this->code = $code;
}
}
$collection = collect(['USD', 'EUR', 'GBP']);
$currencies = $collection->mapInto(Currency::class);
$currencies->all();
// [Currency('USD'), Currency('EUR'), Currency('GBP')]
$collection = collect([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
$chunks = $collection->chunk(2);
$sequence = $chunks->mapSpread(function ($even, $odd) {
return $even + $odd;
});
$sequence->all();
// [1, 5, 9, 13, 17]
$collection = collect([
[
'name' => 'John Doe',
'department' => 'Sales',
],
[
'name' => 'Jane Doe',
'department' => 'Sales',
],
[
'name' => 'Johnny Doe',
'department' => 'Marketing',
]
]);
$grouped = $collection->mapToGroups(function ($item, $key) {
return [$item['department'] => $item['name']];
});
$grouped->all();
/*
[
'Sales' => ['John Doe', 'Jane Doe'],
'Marketing' => ['Johnny Doe'],
]
*/
$grouped->get('Sales')->all();
// ['John Doe', 'Jane Doe']
$collection = collect([
[
'name' => 'John',
'department' => 'Sales',
'email' => 'john@example.com',
],
[
'name' => 'Jane',
'department' => 'Marketing',
'email' => 'jane@example.com',
]
]);
$keyed = $collection->mapWithKeys(function ($item, $key) {
return [$item['email'] => $item['name']];
});
$keyed->all();
/*
[
'john@example.com' => 'John',
'jane@example.com' => 'Jane',
]
*/
$max = collect([
['foo' => 10],
['foo' => 20]
])->max('foo');
// 20
$max = collect([1, 2, 3, 4, 5])->max();
// 5
$median = collect([
['foo' => 10],
['foo' => 10],
['foo' => 20],
['foo' => 40]
])->median('foo');
// 15
$median = collect([1, 1, 2, 4])->median();
// 1.5
$collection = collect(['product_id' => 1, 'price' => 100]);
$merged = $collection->merge(['price' => 200, 'discount' => false]);
$merged->all();
// ['product_id' => 1, 'price' => 200, 'discount' => false]
Hoặc
$collection = collect(['Desk', 'Chair']);
$merged = $collection->merge(['Bookcase', 'Door']);
$merged->all();
// ['Desk', 'Chair', 'Bookcase', 'Door']
$collection = collect(['product_id' => 1, 'price' => 100]);
$merged = $collection->mergeRecursive([
'product_id' => 2,
'price' => 200,
'discount' => false
]);
$merged->all();
// ['product_id' => [1, 2], 'price' => [100, 200], 'discount' => false]
$min = collect([['foo' => 10], ['foo' => 20]])->min('foo');
// 10
$min = collect([1, 2, 3, 4, 5])->min();
// 1
$mode = collect([
['foo' => 10],
['foo' => 10],
['foo' => 20],
['foo' => 40]
])->mode('foo');
// [10]
$mode = collect([1, 1, 2, 4])->mode();
// [1]
$mode = collect([1, 1, 2, 2])->mode();
// [1, 2]
$collection = collect(['a', 'b', 'c', 'd', 'e', 'f']);
$collection->nth(4);
// ['a', 'e']
Hoặc
$collection->nth(4, 1);
// ['b', 'f']
$collection = collect([
'product_id' => 1,
'name' => 'Desk',
'price' => 100,
'discount' => false
]);
$filtered = $collection->only(['product_id', 'name']);
$filtered->all();
// ['product_id' => 1, 'name' => 'Desk']
$collection = collect(['A', 'B', 'C']);
$filtered = $collection->pad(5, 0);
$filtered->all();
// ['A', 'B', 'C', 0, 0]
$filtered = $collection->pad(-5, 0);
$filtered->all();
// [0, 0, 'A', 'B', 'C']
$collection = collect([1, 2, 3, 4, 5, 6]);
[$underThree, $equalOrAboveThree] = $collection->partition(function ($i) {
return $i < 3;
});
$underThree->all();
// [1, 2]
$equalOrAboveThree->all();
// [3, 4, 5, 6]
$collection = collect([1, 2, 3]);
$piped = $collection->pipe(function ($collection) {
return $collection->sum();
});
// 6
class ResourceCollection
{
/**
* The Collection instance.
*/
public $collection;
/**
* Create a new ResourceCollection instance.
*
* @param Collection $collection
* @return void
*/
public function __construct(Collection $collection)
{
$this->collection = $collection;
}
}
$collection = collect([1, 2, 3]);
$resource = $collection->pipeInto(ResourceCollection::class);
$resource->collection->all();
// [1, 2, 3]
$collection = collect([1, 2, 3]);
$result = $collection->pipeThrough([
function ($collection) {
return $collection->merge([4, 5]);
},
function ($collection) {
return $collection->sum();
},
]);
// 15
$collection = collect([
['product_id' => 'prod-100', 'name' => 'Desk'],
['product_id' => 'prod-200', 'name' => 'Chair'],
]);
$plucked = $collection->pluck('name');
$plucked->all();
// ['Desk', 'Chair']
Hoặc
$plucked = $collection->pluck('name', 'product_id');
$plucked->all();
// ['prod-100' => 'Desk', 'prod-200' => 'Chair']
Hoặc
$collection = collect([
[
'name' => 'Laracon',
'speakers' => [
'first_day' => ['Rosa', 'Judith'],
],
],
[
'name' => 'VueConf',
'speakers' => [
'first_day' => ['Abigail', 'Joey'],
],
],
]);
$plucked = $collection->pluck('speakers.first_day');
$plucked->all();
// [['Rosa', 'Judith'], ['Abigail', 'Joey']]
Hoặc
$collection = collect([
['brand' => 'Tesla', 'color' => 'red'],
['brand' => 'Pagani', 'color' => 'white'],
['brand' => 'Tesla', 'color' => 'black'],
['brand' => 'Pagani', 'color' => 'orange'],
]);
$plucked = $collection->pluck('color', 'brand');
$plucked->all();
// ['Tesla' => 'black', 'Pagani' => 'orange']
$collection = collect([1, 2, 3, 4, 5]);
$collection->pop();
// 5
$collection->all();
// [1, 2, 3, 4]
Hoặc
$collection = collect([1, 2, 3, 4, 5]);
$collection->pop(3);
// collect([5, 4, 3])
$collection->all();
// [1, 2]
$collection = collect([1, 2, 3, 4, 5]);
$collection->prepend(0);
$collection->all();
// [0, 1, 2, 3, 4, 5]
Hoặc
$collection = collect(['one' => 1, 'two' => 2]);
$collection->prepend(0, 'zero');
$collection->all();
// ['zero' => 0, 'one' => 1, 'two' => 2]
$collection = collect(['product_id' => 'prod-100', 'name' => 'Desk']);
$collection->pull('name');
// 'Desk'
$collection->all();
// ['product_id' => 'prod-100']
$collection = collect([1, 2, 3, 4]);
$collection->push(5);
$collection->all();
// [1, 2, 3, 4, 5]
$collection = collect(['product_id' => 1, 'name' => 'Desk']);
$collection->put('price', 100);
$collection->all();
// ['product_id' => 1, 'name' => 'Desk', 'price' => 100]
$collection = collect([1, 2, 3, 4, 5]);
$collection->random();
// 4 - (retrieved randomly)
Hoặc
$random = $collection->random(3);
$random->all();
// [2, 4, 5] - (retrieved randomly)
$collection = collect()->range(3, 6);
$collection->all();
// [3, 4, 5, 6]
$collection = collect([1, 2, 3]);
$total = $collection->reduce(function ($carry, $item) {
return $carry + $item;
});
// 6
Hoặc
$collection->reduce(function ($carry, $item) {
return $carry + $item;
}, 4);
// 10
Hoặc
$collection = collect([
'usd' => 1400,
'gbp' => 1200,
'eur' => 1000,
]);
$ratio = [
'usd' => 1,
'gbp' => 1.37,
'eur' => 1.22,
];
$collection->reduce(function ($carry, $value, $key) use ($ratio) {
return $carry + ($value * $ratio[$key]);
});
// 4264
Chú ý 😒😒😒
$collection = collect([
'usd' => 1400,
'gbp' => 1200,
'eur' => 1000,
]);
$ratio = [
'usd' => 1,
'gbp' => 1.37,
'eur' => 1.22,
];
$collection->reduce(function ($carry, $value, $key) use ($ratio) {
echo '<pre>';
var_export($ratio);
echo '</pre>';
return $carry + ($value * $ratio[$key]);
});
die(" ");
Result
array (
'usd' => 1,
'gbp' => 1.37,
'eur' => 1.22,
)
array (
'usd' => 1,
'gbp' => 1.37,
'eur' => 1.22,
)
array (
'usd' => 1,
'gbp' => 1.37,
'eur' => 1.22,
)
reduceSpread()
?? chưa hiểu??? 😒😒
[$creditsRemaining, $batch] = Image::where('status', 'unprocessed')
->get()
->reduceSpread(function ($creditsRemaining, $batch, $image) {
if ($creditsRemaining >= $image->creditsRequired()) {
$batch->push($image);
$creditsRemaining -= $image->creditsRequired();
}
return [$creditsRemaining, $batch];
}, $creditsAvailable, collect());
$collection = collect([1, 2, 3, 4]);
$filtered = $collection->reject(function ($value, $key) {
return $value > 2;
});
$filtered->all();
// [1, 2]
$collection = collect(['Taylor', 'Abigail', 'James']);
$replaced = $collection->replace([1 => 'Victoria', 3 => 'Finn']);
$replaced->all();
// ['Taylor', 'Victoria', 'James', 'Finn']
$collection = collect([
'Taylor',
'Abigail',
[
'James',
'Victoria',
'Finn'
]
]);
$replaced = $collection->replaceRecursive([
'Charlie',
2 => [1 => 'King']
]);
$replaced->all();
// ['Charlie', 'Abigail', ['James', 'King', 'Finn']]
$collection = collect(['a', 'b', 'c', 'd', 'e']);
$reversed = $collection->reverse();
$reversed->all();
/*
[
4 => 'e',
3 => 'd',
2 => 'c',
1 => 'b',
0 => 'a',
]
*/
$collection = collect([2, 4, 6, 8]);
$collection->search(4);
// 1
Hoặc
collect([2, 4, 6, 8])->search('4', $strict = true);
// false
Hoặc
collect([2, 4, 6, 8])->search(function ($item, $key) {
return $item > 5;
});
// 2
$collection = collect([1, 2, 3, 4, 5]);
$collection->shift();
// 1
$collection->all();
// [2, 3, 4, 5]
Hoặc
$collection = collect([1, 2, 3, 4, 5]);
$collection->shift(3);
// collect([1, 2, 3])
$collection->all();
// [4, 5]
$collection = collect([1, 2, 3, 4, 5]);
$shuffled = $collection->shuffle();
$shuffled->all();
// [3, 2, 5, 1, 4] - (generated randomly)
$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
$collection = $collection->skip(4);
$collection->all();
// [5, 6, 7, 8, 9, 10]
$collection = collect([1, 2, 3, 4]);
$subset = $collection->skipUntil(function ($item) {
return $item >= 3;
});
$subset->all();
// [3, 4]
Hoặc
$collection = collect([1, 2, 3, 4]);
$subset = $collection->skipUntil(3);
$subset->all();
// [3, 4]
$collection = collect([1, 2, 3, 4]);
$subset = $collection->skipWhile(function ($item) {
return $item <= 3;
});
$subset->all();
// [4]
$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
$slice = $collection->slice(4);
$slice->all();
// [5, 6, 7, 8, 9, 10]
Hoặc
$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
$slice = $collection->slice(4, 2);
$slice->all();
// [5, 6]
$collection = collect([1, 2, 3, 4, 5]);
$chunks = $collection->sliding(2);
$chunks->toArray();
// [[1, 2], [2, 3], [3, 4], [4, 5]]
Hoặc
$collection = collect([1, 2, 3, 4, 5]);
$chunks = $collection->sliding(3, step: 2);
$chunks->toArray();
// [[1, 2, 3], [3, 4, 5]]
collect([1, 2, 3, 4])->sole(function ($value, $key) {
return $value === 2;
});
// 2
Hoặc
$collection = collect([
['product' => 'Desk', 'price' => 200],
['product' => 'Chair', 'price' => 100],
]);
$collection->sole('product', 'Chair');
// ['product' => 'Chair', 'price' => 100]
Hoặc
$collection = collect([
['product' => 'Desk', 'price' => 200],
]);
$collection->sole();
// ['product' => 'Desk', 'price' => 200]
$collection = collect([5, 3, 1, 2, 4]);
$sorted = $collection->sort();
$sorted->values()->all();
// [1, 2, 3, 4, 5]
$collection = collect([
['name' => 'Desk', 'price' => 200],
['name' => 'Chair', 'price' => 100],
['name' => 'Bookcase', 'price' => 150],
]);
$sorted = $collection->sortBy('price');
$sorted->values()->all();
/*
[
['name' => 'Chair', 'price' => 100],
['name' => 'Bookcase', 'price' => 150],
['name' => 'Desk', 'price' => 200],
]
*/
Hoặc
$collection = collect([
['title' => 'Item 1'],
['title' => 'Item 12'],
['title' => 'Item 3'],
]);
$sorted = $collection->sortBy('title', SORT_NATURAL);
$sorted->values()->all();
/*
[
['title' => 'Item 1'],
['title' => 'Item 3'],
['title' => 'Item 12'],
]
*/
Hoặc
$collection = collect([
['name' => 'Desk', 'colors' => ['Black', 'Mahogany']],
['name' => 'Chair', 'colors' => ['Black']],
['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']],
]);
$sorted = $collection->sortBy(function ($product, $key) {
return count($product['colors']);
});
$sorted->values()->all();
/*
[
['name' => 'Chair', 'colors' => ['Black']],
['name' => 'Desk', 'colors' => ['Black', 'Mahogany']],
['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']],
]
*/
Hoặc
$collection = collect([
['name' => 'Taylor Otwell', 'age' => 34],
['name' => 'Abigail Otwell', 'age' => 30],
['name' => 'Taylor Otwell', 'age' => 36],
['name' => 'Abigail Otwell', 'age' => 32],
]);
$sorted = $collection->sortBy([
['name', 'asc'],
['age', 'desc'],
]);
$sorted->values()->all();
/*
[
['name' => 'Abigail Otwell', 'age' => 32],
['name' => 'Abigail Otwell', 'age' => 30],
['name' => 'Taylor Otwell', 'age' => 36],
['name' => 'Taylor Otwell', 'age' => 34],
]
*/
Hoặc
$collection = collect([
['name' => 'Taylor Otwell', 'age' => 34],
['name' => 'Abigail Otwell', 'age' => 30],
['name' => 'Taylor Otwell', 'age' => 36],
['name' => 'Abigail Otwell', 'age' => 32],
]);
$sorted = $collection->sortBy([
fn ($a, $b) => $a['name'] <=> $b['name'],
fn ($a, $b) => $b['age'] <=> $a['age'],
]);
$sorted->values()->all();
/*
[
['name' => 'Abigail Otwell', 'age' => 32],
['name' => 'Abigail Otwell', 'age' => 30],
['name' => 'Taylor Otwell', 'age' => 36],
['name' => 'Taylor Otwell', 'age' => 34],
]
*/
$collection = collect([5, 3, 1, 2, 4]);
$sorted = $collection->sortDesc();
$sorted->values()->all();
// [5, 4, 3, 2, 1]
$collection = collect([
'id' => 22345,
'first' => 'John',
'last' => 'Doe',
])
$sorted = $collection->sortKeys();
$sorted->all();
/*
[
'first' => 'John',
'id' => 22345,
'last' => 'Doe',
]
*/
$collection = collect([
'ID' => 22345,
'first' => 'John',
'last' => 'Doe',
]);
$sorted = $collection->sortKeysUsing('strnatcasecmp');
$sorted->all();
/*
[
'first' => 'John',
'ID' => 22345,
'last' => 'Doe',
]
*/
$collection = collect([1, 2, 3, 4, 5]);
$chunk = $collection->splice(2);
$chunk->all();
// [3, 4, 5]
$collection->all();
// [1, 2]
Hoặc
$collection = collect([1, 2, 3, 4, 5]);
$chunk = $collection->splice(2, 1);
$chunk->all();
// [3]
$collection->all();
// [1, 2, 4, 5]
$collection = collect([1, 2, 3, 4, 5]);
$groups = $collection->split(3);
$groups->all();
// [[1, 2], [3, 4], [5]]
$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
$groups = $collection->splitIn(3);
$groups->all();
// [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]
collect([1, 2, 3, 4, 5])->sum();
// 15
Hoặc
$collection = collect([
['name' => 'JavaScript: The Good Parts', 'pages' => 176],
['name' => 'JavaScript: The Definitive Guide', 'pages' => 1096],
]);
$collection->sum('pages');
// 1272
Hoặc
$collection = collect([
['name' => 'Chair', 'colors' => ['Black']],
['name' => 'Desk', 'colors' => ['Black', 'Mahogany']],
['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']],
]);
$collection->sum(function ($product) {
return count($product['colors']);
});
// 6
$collection = collect([0, 1, 2, 3, 4, 5]);
$chunk = $collection->take(3);
$chunk->all();
// [0, 1, 2]
Hoặc
$collection = collect([0, 1, 2, 3, 4, 5]);
$chunk = $collection->take(-2);
$chunk->all();
// [4, 5]
$collection = collect([1, 2, 3, 4]);
$subset = $collection->takeUntil(function ($item) {
return $item >= 3;
});
$subset->all();
// [1, 2]
Hoặc
$collection = collect([1, 2, 3, 4]);
$subset = $collection->takeUntil(3);
$subset->all();
// [1, 2]
$collection = collect([1, 2, 3, 4]);
$subset = $collection->takeWhile(function ($item) {
return $item < 3;
});
$subset->all();
// [1, 2]
$collection = Collection::times(10, function ($number) {
return $number * 9;
});
$collection->all();
// [9, 18, 27, 36, 45, 54, 63, 72, 81, 90]
$collection = collect(['name' => 'Desk', 'price' => 200]);
$collection->toArray();
/*
[
['name' => 'Desk', 'price' => 200],
]
*/
$collection = collect(['name' => 'Desk', 'price' => 200]);
$collection->toJson();
// '{"name":"Desk", "price":200}'
$collection = collect([1, 2, 3, 4, 5]);
$collection->transform(function ($item, $key) {
return $item * 2;
});
$collection->all();
// [2, 4, 6, 8, 10]
$person = collect([
'name.first_name' => 'Marie',
'name.last_name' => 'Valentine',
'address.line_1' => '2992 Eagle Drive',
'address.line_2' => '',
'address.suburb' => 'Detroit',
'address.state' => 'MI',
'address.postcode' => '48219'
]);
$person = $person->undot();
$person->toArray();
/*
[
"name" => [
"first_name" => "Marie",
"last_name" => "Valentine",
],
"address" => [
"line_1" => "2992 Eagle Drive",
"line_2" => "",
"suburb" => "Detroit",
"state" => "MI",
"postcode" => "48219",
],
]
*/
$collection = collect([1 => ['a'], 2 => ['b']]);
$union = $collection->union([3 => ['c'], 1 => ['d']]);
$union->all();
// [1 => ['a'], 2 => ['b'], 3 => ['c']]
$collection = collect([1, 1, 2, 2, 3, 4, 2]);
$unique = $collection->unique();
$unique->values()->all();
// [1, 2, 3, 4]
Hoặc
$collection = collect([
['name' => 'iPhone 6', 'brand' => 'Apple', 'type' => 'phone'],
['name' => 'iPhone 5', 'brand' => 'Apple', 'type' => 'phone'],
['name' => 'Apple Watch', 'brand' => 'Apple', 'type' => 'watch'],
['name' => 'Galaxy S6', 'brand' => 'Samsung', 'type' => 'phone'],
['name' => 'Galaxy Gear', 'brand' => 'Samsung', 'type' => 'watch'],
]);
$unique = $collection->unique('brand');
$unique->values()->all();
/*
[
['name' => 'iPhone 6', 'brand' => 'Apple', 'type' => 'phone'],
['name' => 'Galaxy S6', 'brand' => 'Samsung', 'type' => 'phone'],
]
*/
Hoặc
$unique = $collection->unique(function ($item) {
return $item['brand'].$item['type'];
});
$unique->values()->all();
/*
[
['name' => 'iPhone 6', 'brand' => 'Apple', 'type' => 'phone'],
['name' => 'Apple Watch', 'brand' => 'Apple', 'type' => 'watch'],
['name' => 'Galaxy S6', 'brand' => 'Samsung', 'type' => 'phone'],
['name' => 'Galaxy Gear', 'brand' => 'Samsung', 'type' => 'watch'],
]
*/
$collection = collect([1, 2, 3]);
$collection->unless(true, function ($collection) {
return $collection->push(4);
});
$collection->unless(false, function ($collection) {
return $collection->push(5);
});
$collection->all();
// [1, 2, 3, 5]
Hoặc
$collection = collect([1, 2, 3]);
$collection->unless(true, function ($collection) {
return $collection->push(4);
}, function ($collection) {
return $collection->push(5);
});
$collection->all();
// [1, 2, 3, 5]
Collection::unwrap(collect('John Doe'));
// ['John Doe']
Collection::unwrap(['John Doe']);
// ['John Doe']
Collection::unwrap('John Doe');
// 'John Doe'
$collection = collect([
['product' => 'Desk', 'price' => 200],
['product' => 'Speaker', 'price' => 400],
]);
$value = $collection->value('price');
// 200
$collection = collect([
10 => ['product' => 'Desk', 'price' => 200],
11 => ['product' => 'Desk', 'price' => 200],
]);
$values = $collection->values();
$values->all();
/*
[
0 => ['product' => 'Desk', 'price' => 200],
1 => ['product' => 'Desk', 'price' => 200],
]
*/
$collection = collect([1, 2, 3]);
$collection->when(true, function ($collection, $value) {
return $collection->push(4);
});
$collection->when(false, function ($collection, $value) {
return $collection->push(5);
});
$collection->all();
// [1, 2, 3, 4]
Hoặc
$collection = collect([1, 2, 3]);
$collection->when(false, function ($collection, $value) {
return $collection->push(4);
}, function ($collection) {
return $collection->push(5);
});
$collection->all();
// [1, 2, 3, 5]
$collection = collect(['Michael', 'Tom']);
$collection->whenEmpty(function ($collection) {
return $collection->push('Adam');
});
$collection->all();
// ['Michael', 'Tom']
$collection = collect();
$collection->whenEmpty(function ($collection) {
return $collection->push('Adam');
});
$collection->all();
// ['Adam']
Hoặc
$collection = collect(['Michael', 'Tom']);
$collection->whenEmpty(function ($collection) {
return $collection->push('Adam');
}, function ($collection) {
return $collection->push('Taylor');
});
$collection->all();
// ['Michael', 'Tom', 'Taylor']
$collection = collect(['michael', 'tom']);
$collection->whenNotEmpty(function ($collection) {
return $collection->push('adam');
});
$collection->all();
// ['michael', 'tom', 'adam']
$collection = collect();
$collection->whenNotEmpty(function ($collection) {
return $collection->push('adam');
});
$collection->all();
// []
$collection = collect([
['product' => 'Desk', 'price' => 200],
['product' => 'Chair', 'price' => 100],
['product' => 'Bookcase', 'price' => 150],
['product' => 'Door', 'price' => 100],
]);
$filtered = $collection->where('price', 100);
$filtered->all();
/*
[
['product' => 'Chair', 'price' => 100],
['product' => 'Door', 'price' => 100],
]
*/
Hoặc
$collection = collect([
['name' => 'Jim', 'deleted_at' => '2019-01-01 00:00:00'],
['name' => 'Sally', 'deleted_at' => '2019-01-02 00:00:00'],
['name' => 'Sue', 'deleted_at' => null],
]);
$filtered = $collection->where('deleted_at', '!=', null);
$filtered->all();
/*
[
['name' => 'Jim', 'deleted_at' => '2019-01-01 00:00:00'],
['name' => 'Sally', 'deleted_at' => '2019-01-02 00:00:00'],
]
*/
$collection = collect([
['product' => 'Desk', 'price' => 200],
['product' => 'Chair', 'price' => 80],
['product' => 'Bookcase', 'price' => 150],
['product' => 'Pencil', 'price' => 30],
['product' => 'Door', 'price' => 100],
]);
$filtered = $collection->whereBetween('price', [100, 200]);
$filtered->all();
/*
[
['product' => 'Desk', 'price' => 200],
['product' => 'Bookcase', 'price' => 150],
['product' => 'Door', 'price' => 100],
]
*/
$collection = collect([
['product' => 'Desk', 'price' => 200],
['product' => 'Chair', 'price' => 100],
['product' => 'Bookcase', 'price' => 150],
['product' => 'Door', 'price' => 100],
]);
$filtered = $collection->whereIn('price', [150, 200]);
$filtered->all();
/*
[
['product' => 'Desk', 'price' => 200],
['product' => 'Bookcase', 'price' => 150],
]
*/
use App\Models\User;
use App\Models\Post;
$collection = collect([
new User,
new User,
new Post,
]);
$filtered = $collection->whereInstanceOf(User::class);
$filtered->all();
// [App\Models\User, App\Models\User]
$collection = collect([
['product' => 'Desk', 'price' => 200],
['product' => 'Chair', 'price' => 80],
['product' => 'Bookcase', 'price' => 150],
['product' => 'Pencil', 'price' => 30],
['product' => 'Door', 'price' => 100],
]);
$filtered = $collection->whereNotBetween('price', [100, 200]);
$filtered->all();
/*
[
['product' => 'Chair', 'price' => 80],
['product' => 'Pencil', 'price' => 30],
]
*/
$collection = collect([
['product' => 'Desk', 'price' => 200],
['product' => 'Chair', 'price' => 100],
['product' => 'Bookcase', 'price' => 150],
['product' => 'Door', 'price' => 100],
]);
$filtered = $collection->whereNotIn('price', [150, 200]);
$filtered->all();
/*
[
['product' => 'Chair', 'price' => 100],
['product' => 'Door', 'price' => 100],
]
*/
$collection = collect([
['name' => 'Desk'],
['name' => null],
['name' => 'Bookcase'],
]);
$filtered = $collection->whereNotNull('name');
$filtered->all();
/*
[
['name' => 'Desk'],
['name' => 'Bookcase'],
]
*/
$collection = collect([
['name' => 'Desk'],
['name' => null],
['name' => 'Bookcase'],
]);
$filtered = $collection->whereNull('name');
$filtered->all();
/*
[
['name' => null],
]
*/
use Illuminate\Support\Collection;
$collection = Collection::wrap('John Doe');
$collection->all();
// ['John Doe']
$collection = Collection::wrap(['John Doe']);
$collection->all();
// ['John Doe']
$collection = Collection::wrap(collect('John Doe'));
$collection->all();
// ['John Doe']
$collection = collect(['Chair', 'Desk']);
$zipped = $collection->zip([100, 200]);
$zipped->all();
// [['Chair', 100], ['Desk', 200]]
😉😉😉 chưa hiểu?
$users = collect([
1 => [
'name' => 'John',
'age' => 31
'is_admin' => false,
],
2 => [
'name' => 'Mike',
'age' => 16
'is_admin' => true,
],
3 => [
'name' => 'Carmen',
'age' => 58
'is_admin' => false,
],
4 => [
'name' => 'Abby',
'age' => 24
'is_admin' => true,
],
]);
Photo by Karen Vardazaryan on Unsplash
If may think that enough tinkering around Laravel’s Collections too much have made you some kind of Collection expert, but Higher Order Messages are one level above in understanding.
One thing I couldn’t grasp, and probably you either if you are reading this, is how they work and what problem they try to solve, but falter not, these are relatively easy to understand when you think about them as proxies to the real methods.
Higher Order Messages are basically properties that act like you were doing a very short closure. To better exemplify, let’s say we want to filter all users who are not admin.
$users = collect([
1 => [
'name' => 'John',
'age' => 31
'is_admin' => false,
],
2 => [
'name' => 'Mike',
'age' => 16
'is_admin' => true,
],
3 => [
'name' => 'Carmen',
'age' => 58
'is_admin' => false,
],
4 => [
'name' => 'Abby',
'age' => 24
'is_admin' => true,
],
]);
You can see that Mike and Abby are admins because the is_admin
is true
, so the first thing you could do to filter them should be to call the filter
method of the Collection to return those who are inside another Collection instance.
$admins = $users->filter(function (array $user) {
return $user['is_admin'];
});
While that line may work for some, we can make the filter a one line. The filter
method as a Higher Order Message by the same name. It will take the value we are using to “get” as the what the closure should return for each item in the collection, being a property or an array key.
$admins = $users->filter->is_admin;
And that’s it, it’s very simple.
Some methods do not return collections, and that’s fine. For example, the sum
method returns the result of a sum on the value of each item.
In this case, we can sum the users who are admins:
$admins = $users->sum(function (array $user) {
return $user['is_admin'] ? 1 : 0;
});
// 2
We can make that whole call into one line, since the sum
method actually does an additive operation in PHP which is compatible with booleans, where true
is 1
and false
is 0
. So, yes, we can sum booleans without any problem.
$admins = $users->sum->is_admin;
// 2
Higher Order Collection are also compatible with methods, including arguments to them. The method you pass will be used for each item, so let’s make an example.
This User
class has a convenient method that returns true
or false
if the age is above to what we’re asking.
class User extends Model
{
public function ageAbove(int $age)
{
return $this->age > $age;
}
}
Let’s assume we have a collection of these User
class instances. The old nasty way to filter them would be using a closure to execute on each of them.
$users = User::all();
$adults = $users->filter(function (User $user) {
return $user->ageAbove(21);
});
And it gets more verbose when we have to include the age from a variable outside the closure.
$adults = $users->filter(function (User $user) use ($age) {
return $user->ageAbove($age);
});
But that can be, again, become a one line:
$adults = $users->filter->ageAbove(21);
And that’s all folks!
Bài đăng này đã không được cập nhật trong 2 năm
Laravel 6.0 đã giới thiệu Lazy Collection. Lazy collection sử dụng PHP generators để cho phép chúng ta làm việc với một tập dữ liệu rất lớn và giữ cho mức sử dụng bộ nhớ ở mức thấp. Ví dụ với 60.000 bản ghi user. Nếu bây giờ chúng ta lấy ra tất cả các bản ghi cùng 1 lúc thì sao? Chúng ta nhận được lỗi 500 do quá tải bộ nhớ, bởi vì tất cả 60.000 user đều được tải vào bộ nhớ cùng lúc.
$users = \App\User::all();
Và để loại bỏ việc sử dụng bộ nhớ này chúng ta sử dụng method cursor()
. Method này cho phép chỉ thực hiện 1 câu truy vấn duy nhất và chỉ 1 Eloquent model được load ra tại 1 thời điểm .
Trong ví dụ này, việc gọi filter
sẽ không được thực thi cho đến khi từng user được lặp lại, làm giảm đáng kể việc sử dụng bộ nhớ
$users = App\User::cursor()->filter(function ($user) {
return $user->id > 500;
});
foreach ($users as $user) {
echo $user->id;
}
Ngoài ra chúng ta có thể sử dụng lazy collection để đọc hàng GB khổng lồ. Method make()
dùng để tạo 1 lazy collection class object
Ví dụ, chúng ta lấy 4 bản ghi với method chuck()
, load các bản ghi vào LogEntry model và lặp qua các bản ghi đó.
use App\LogEntry;
use Illuminate\Support\LazyCollection;
LazyCollection::make(function () {
$handle = fopen('log.txt', 'r');
while (($line = fgets($handle)) !== false) {
yield $line;
}
})
->chunk(4)
->map(function ($lines) {
return LogEntry::fromLines($lines);
})
->each(function (LogEntry $logEntry) {
// Process the log entry...
});
Điểm chú ý ở đây chính là việc ta sử dụng hàm yield
của php thay choreturn
như Collection. Thay vì dừng thực thi hàm và trả về (return), yield
trả về giá trị khi giá trị đó cần sử dụng đến mà không lưu trữ tất cả các giá trị trong bộ nhớ.
Ban có thể tìm hiểu thêm về yield tại đây
Tìm hiểu Lazy Collection
Introduction
Lazy Collection là một tính năng mới của Laravel được giới thiệu trong phiên bản 6.0. Đây là một sự bổ sung cho tính năng Collection vô cùng hữu ích đã có trước đó của Laravel cho phép ta giảm thiểu bộ nhớ sử dụng. Vì là một tính năng mới, hiện các tài liệu về Lazy Collection vẫn còn hạn hẹp nên mình xin phép góp vui một bài viết đi vào tìm hiểu về Lazy Collection và có một cái nhìn vào cách nó hoạt động thông qua PHP Generators.
Mục lục
I. Lazy Collection
II. PHP Generators
I. Lazy Collection
1. Giới thiệu
Trong các bài toán thực tế, chúng ta sẽ có thể gặp các tình huống cần làm việc với một lượng lớn các bản ghi như dữ liệu về log hay notifications. Tuy nhiên, việc lấy ra số lượng lớn như vậy để làm việc với Collection thì không khả thi chút nào, đặc biệt với các hệ thống đã chạy lâu năm. Chương trình của chúng ta được triển khai trên một server vật lý với dung lượng RAM giới hạn, việc đọc một lượng lớn các bản ghi sẽ khiến server nhanh chóng quá tải và gây chết trang. Để giảm thiểu vấn đề này, Laravel đã cho ra đời Lazy Collection.
2. Sử dụng
a. Tổng quát
Lazy Collection là một tính năng mới được thêm vào phiên bản Laravel 6.0 cho phép ta làm việc với bộ dữ liệu lớn và duy trì bộ nhớ sử dụng lợi dụng PHP Generators.
b. Khởi tạo Lazy Collection
Tương tự như Collection, để sử dụng LazyCollection ta có thể thêm use Illuminate\Support\LazyCollection vào đầu file.
VD:
use Illuminate\Support\LazyCollection;
LazyCollection::make(function () {
$handle = fopen('log.txt', 'r');
while (($line = fgets($handle)) !== false) {
yield $line;
}
});
Bên cạnh đó, query builder cũng cung cấp cho chúng ta hàm cursor() trả về một LazyCollection cho phép ta làm việc trên nhiều bản ghi nhưng không phải tải toàn bộ vào bộ nhớ cùng lúc.
VD: Giả sử chúng ta có 100,000 bản ghi log hệ thống cần xử lý.
use App\Models\Log;
// không dùng lazy collection, truy vấn thực hiện lấy toàn bộ 100,000 bản ghi vào RAM
Log::all()->map(function ($log, $key) {
return parseMessage($log->message);
});
// sử dụng lazy collection, lần lượt từng model được thêm vào bộ nhớ nhưng chỉ cần 1 query
Log::cursor()->map(function ($log, $key) {
return parseMessage($log->message);
});
c. Các phương thức
Giống với Collection, Lazy Collection implement Illuminate\Support\Enumerable và cung cấp đầy đủ các phương thức thông thường như all(), map(), sort(), where(), v.v... Mọi người có thể xem chi tiết trong tài liệu tham khảo.
Tuy nhiên, bên cạnh đó LazyCollection cũng bao gồm các phương thức mới như:
takeUntilTimeout(DateTimeInterface $timeout): Hàm sẽ thực hiện lấy ra các giá trị tới khi hết thời gian. (LƯU Ý: phương thức này có từ bản 8.x)
tapEach(callable $callback): gần giống với each(), phương thức sẽ thực hiện hàm callback cho từng item nhưng chỉ thực hiện lần lượt cho từng item khi được lấy ra một cách "lazy".
remember(): ghi nhớ các giá trị đã được lấy ra và bỏ qua chúng khi gặp lại.
II. PHP Generators
Như đã nêu trên, để Lazy Collection có thể thực hiện lấy lần lượt các bản ghi vào bộ nhớ chúng ta sử dụng PHP Generator. Một hàm generator nhìn qua không khác so với một PHP function thông thường ngoại trừ việc sử dụng yield thay vì return. Vậy sự khác biệt là gì?
Giả sử ta có một hàm countToMillion() được cài đặt như sau
function countToMillion()
{
for($i = 1; $i <= 1000000; $i++) {
return $i;
}
}
dump(countToMillion());
Output:
1
Hàm thực hiện trả về giá trị đầu tiên và dừng hoàn toàn countToMillion(). Nếu ta thay đổi từ khóa return sang yield, ta sẽ có như sau:
function countToMillion()
{
for($i = 1; $i <= 1000000; $i++) {
yield $i;
}
}
dump(countToMillion());
Output:
Generator {#1534 ▼
executing: {
...
}
closed: false
}
Như ta thấy, từ khóa yield sẽ trả về một Generator object thay vì giá trị "1". Vậy Generator object này có gì đặc biệt?
Tìm hiểu tiếp theo ta sẽ thử thực hiện in lần lượt từng số đếm tới 1 triệu. Để làm được điều đó sử dụng return chúng ta sẽ cần phải lưu lại 1,000,000 bản ghi vào một biến số trước khi trả về.
function countToMillion()
{
$data = [];
for($i = 1; $i <= 1000000; $i++) {
$data[] = $i;
}
return $data;
}
foreach (countToMillion() as $number) {
dump($number);
}
Output:
1
2
3
...
1000000
Điều này gây tốn rất nhiều bộ nhớ. Nhưng khác với return, yield không thực sự dừng hoàn toàn phương thức của chúng ta mà thay vào đó tạm dừng ở vị trí đang đứng. Sử dụng Generator object chúng ta có thể thực hiện lặp qua từng yield để lấy giá trị tiếp theo trả về và giải phóng bộ nhớ sau khi hoàn thành.
// count with yield
...
foreach (countToMillion() as $number) {
dump($number);
}
Output:
1
2
3
...
1000000
Dựa trên ý tưởng này, Laravel Lazy Collection thực hiện xử lý lần lượt các item trong Collection thay vì lưu tất cả vào bộ nhớ.
Tổng kết
Vậy qua bài viết trên chúng ta đã hiểu được cách sử dụng của Lazy Collection và có một cái nhìn sâu hơn về cách nó hoạt động thông qua PHP Generators.