本文目录导读:

我来详细介绍PHP中的集合(Collection) 和流式操作(Stream Operations)。
PHP集合操作
基础数组集合操作
<?php
// 基础集合数据
$users = [
['id' => 1, 'name' => 'Alice', 'age' => 25, 'city' => 'Beijing'],
['id' => 2, 'name' => 'Bob', 'age' => 30, 'city' => 'Shanghai'],
['id' => 3, 'name' => 'Charlie', 'age' => 22, 'city' => 'Beijing'],
['id' => 4, 'name' => 'David', 'age' => 35, 'city' => 'Guangzhou'],
];
// 过滤
$beijingUsers = array_filter($users, fn($user) => $user['city'] === 'Beijing');
// 映射
$names = array_map(fn($user) => $user['name'], $users);
// 排序
usort($users, fn($a, $b) => $a['age'] - $b['age']);
// 分组
$groupByCity = [];
foreach ($users as $user) {
$groupByCity[$user['city']][] = $user;
}
使用Laravel Collection
<?php
use Illuminate\Support\Collection;
$collection = collect([
['id' => 1, 'name' => 'Alice', 'age' => 25],
['id' => 2, 'name' => 'Bob', 'age' => 30],
['id' => 3, 'name' => 'Charlie', 'age' => 22],
]);
// 链式操作
$result = $collection
->where('age', '>', 23)
->sortBy('name')
->take(2)
->values()
->toArray();
// 高级操作
$averageAge = $collection->avg('age');
$maxAge = $collection->max('age');
$groupByName = $collection->groupBy(function($item) {
return strtoupper(substr($item['name'], 0, 1));
});
自定义Collection类
<?php
class SimpleCollection implements ArrayAccess, Countable, IteratorAggregate {
private array $items;
public function __construct(array $items = []) {
$this->items = $items;
}
// 过滤
public function filter(callable $callback): self {
return new self(array_filter($this->items, $callback));
}
// 映射
public function map(callable $callback): self {
return new self(array_map($callback, $this->items));
}
// 排序
public function sort(callable $callback): self {
$items = $this->items;
usort($items, $callback);
return new self($items);
}
// 获取最大值
public function max(?string $key = null): mixed {
if ($key === null) {
return max($this->items);
}
return max(array_column($this->items, $key));
}
// 链式操作示例
public function processChain(): self {
return $this
->filter(fn($item) => $item['active'] === true)
->sort(fn($a, $b) => $a['priority'] <=> $b['priority'])
->map(fn($item) => array_merge($item, ['processed' => true]));
}
public function getIterator(): ArrayIterator {
return new ArrayIterator($this->items);
}
public function count(): int {
return count($this->items);
}
public function offsetExists($offset): bool {
return isset($this->items[$offset]);
}
public function offsetGet($offset): mixed {
return $this->items[$offset] ?? null;
}
public function offsetSet($offset, $value): void {
if ($offset === null) {
$this->items[] = $value;
} else {
$this->items[$offset] = $value;
}
}
public function offsetUnset($offset): void {
unset($this->items[$offset]);
}
}
PHP流式操作
流式文件处理
<?php
// 读取大文件
function processLargeFile(string $filename, callable $handler): void {
$handle = fopen($filename, 'r');
if ($handle === false) {
throw new RuntimeException("Cannot open file: $filename");
}
while (($line = fgets($handle)) !== false) {
$handler(trim($line));
}
fclose($handle);
}
// 使用生成器实现流式处理
function readLines(string $filename): Generator {
$handle = fopen($filename, 'r');
if ($handle === false) {
throw new RuntimeException("Cannot open file: $filename");
}
while (($line = fgets($handle)) !== false) {
yield trim($line);
}
fclose($handle);
}
// 使用示例
$lines = readLines('large_file.txt');
foreach ($lines as $lineNumber => $line) {
echo "Line $lineNumber: $line\n";
}
流式数据转换管道
<?php
class StreamPipeline {
private array $operations = [];
private mixed $data;
public function __construct(mixed $data) {
$this->data = $data;
}
public function filter(callable $callback): self {
$this->operations[] = function($data) use ($callback) {
return array_filter($data, $callback);
};
return $this;
}
public function map(callable $callback): self {
$this->operations[] = function($data) use ($callback) {
return array_map($callback, $data);
};
return $this;
}
public function reduce(callable $callback, mixed $initial = null): self {
$this->operations[] = function($data) use ($callback, $initial) {
return array_reduce($data, $callback, $initial);
};
return $this;
}
public function execute(): mixed {
$result = $this->data;
foreach ($this->operations as $operation) {
$result = $operation($result);
}
return $result;
}
}
// 使用示例
$pipeline = new StreamPipeline([1, 2, 3, 4, 5, 6]);
$result = $pipeline
->filter(fn($n) => $n % 2 === 0) // 只保留偶数
->map(fn($n) => $n * 2) // 每个数乘以2
->reduce(fn($carry, $n) => $carry + $n, 0) // 求和
->execute();
echo $result; // 输出: 24
高级流式操作实现
<?php
class Stream {
private array $data;
private array $pipeline = [];
public function __construct(array $data) {
$this->data = $data;
}
public static function of(array $data): self {
return new self($data);
}
// 过滤操作
public function filter(callable $predicate): self {
$this->pipeline[] = function($data) use ($predicate) {
return array_values(array_filter($data, $predicate));
};
return $this;
}
// 映射操作
public function map(callable $mapper): self {
$this->pipeline[] = function($data) use ($mapper) {
return array_map($mapper, $data);
};
return $this;
}
// 扁平化映射
public function flatMap(callable $mapper): self {
$this->pipeline[] = function($data) use ($mapper) {
$result = [];
foreach ($data as $item) {
$result = array_merge($result, $mapper($item));
}
return $result;
};
return $this;
}
// 去重
public function distinct(): self {
$this->pipeline[] = function($data) {
return array_values(array_unique($data, SORT_REGULAR));
};
return $this;
}
// 排序
public function sorted(?callable $comparator = null): self {
$this->pipeline[] = function($data) use ($comparator) {
$sorted = $data;
if ($comparator) {
usort($sorted, $comparator);
} else {
sort($sorted);
}
return $sorted;
};
return $this;
}
// 限制数量
public function limit(int $limit): self {
$this->pipeline[] = function($data) use ($limit) {
return array_slice($data, 0, $limit);
};
return $this;
}
// 跳过
public function skip(int $count): self {
$this->pipeline[] = function($data) use ($count) {
return array_slice($data, $count);
};
return $this;
}
// 收集结果
public function collect(): array {
$result = $this->data;
foreach ($this->pipeline as $operation) {
$result = $operation($result);
}
return $result;
}
// 获取第一个元素
public function first(): mixed {
$result = $this->collect();
return !empty($result) ? $result[0] : null;
}
// 统计
public function count(): int {
return count($this->collect());
}
// 判断是否所有元素满足条件
public function allMatch(callable $predicate): bool {
foreach ($this->data as $item) {
if (!$predicate($item)) {
return false;
}
}
return true;
}
// 判断是否存在满足条件的元素
public function anyMatch(callable $predicate): bool {
foreach ($this->data as $item) {
if ($predicate($item)) {
return true;
}
}
return false;
}
}
// 使用示例
$people = [
['name' => 'Alice', 'age' => 25, 'department' => 'IT'],
['name' => 'Bob', 'age' => 30, 'department' => 'HR'],
['name' => 'Charlie', 'age' => 22, 'department' => 'IT'],
['name' => 'David', 'age' => 35, 'department' => 'Finance'],
];
$result = Stream::of($people)
->filter(fn($p) => $p['age'] > 23)
->map(fn($p) => [
'name' => $p['name'],
'age' => $p['age'],
'seniority' => $p['age'] > 30 ? 'Senior' : 'Junior'
])
->sorted(fn($a, $b) => $a['age'] <=> $b['age'])
->limit(3)
->collect();
print_r($result);
惰性求值实现
<?php
class LazyStream {
private Generator $generator;
private array $operations = [];
public function __construct(Generator $generator) {
$this->generator = $generator;
}
public function filter(callable $predicate): self {
$this->operations[] = function(Generator $gen) use ($predicate) {
foreach ($gen as $item) {
if ($predicate($item)) {
yield $item;
}
}
};
return $this;
}
public function map(callable $mapper): self {
$this->operations[] = function(Generator $gen) use ($mapper) {
foreach ($gen as $item) {
yield $mapper($item);
}
};
return $this;
}
// 惰性执行,只在需要时计算结果
public function execute(): Generator {
$currentGen = $this->generator;
foreach ($this->operations as $operation) {
$currentGen = $operation($currentGen);
}
return $currentGen;
}
}
// 使用示例 - 处理大量数据
function generateLargeDataset(int $count): Generator {
for ($i = 0; $i < $count; $i++) {
yield ['id' => $i, 'value' => rand(1, 1000)];
}
}
$stream = new LazyStream(generateLargeDataset(1000000));
$result = $stream
->filter(fn($item) => $item['value'] > 500)
->map(fn($item) => $item['id'] * 2)
->execute();
// 只在遍历时真正计算
foreach ($result as $value) {
echo $value . "\n";
}
实际应用场景
数据清洗管道
<?php
class DataCleaningPipeline {
public function process(array $data): array {
return Stream::of($data)
->filter(fn($item) => !empty($item['email'])) // 过滤空邮箱
->map(fn($item) => [
...$item,
'email' => strtolower(trim($item['email'])), // 清洗数据
'phone' => preg_replace('/[^0-9]/', '', $item['phone'] ?? '')
])
->distinct() // 去重
->sorted(fn($a, $b) => $a['created_at'] <=> $b['created_at']) // 按时间排序
->collect();
}
}
报表生成
<?php
class ReportGenerator {
public function generateSalesReport(array $transactions): array {
return Stream::of($transactions)
->filter(fn($t) => $t['status'] === 'completed')
->groupBy(fn($t) => $t['product_id'])
->map(function($group) {
return [
'product_id' => $group[0]['product_id'],
'total_sales' => array_sum(array_column($group, 'amount')),
'count' => count($group),
'average' => array_sum(array_column($group, 'amount')) / count($group)
];
})
->sorted(fn($a, $b) => $b['total_sales'] <=> $a['total_sales'])
->take(10)
->collect();
}
}
这些集合和流式操作模式可以大幅提高PHP代码的可读性和维护性,特别适合数据处理、批量操作和管道式转换等场景。