在 PHP 中,array_filter() 是一个非常强大的函数,它可以根据我们传入的回调函数对数组进行过滤。但是,在大型项目或多处使用相似过滤逻辑的场景下,直接在每个调用点编写匿名函数并不利于代码的复用与维护。本文将介绍如何将 array_filter() 的过滤逻辑封装成一个可复用的组件,让你的代码更优雅、更可维护。
我们先来看看最基本的用法:
$data = [1, 2, 3, 4, 5];
// 过滤出偶数
$filtered = array_filter($data, function($item) {
return $item % 2 === 0;
});
print_r($filtered);
上面的代码虽然简单,但如果我们在多个地方都需要“过滤偶数”这个逻辑,就会面临代码重复的问题。
我们可以将常用的过滤逻辑封装到一个类中,并通过统一的接口调用,从而实现可复用性。
class ArrayFilter
{
protected array $data;
public function __construct(array $data)
{
$this->data = $data;
}
public function filter(callable $callback): array
{
return array_filter($this->data, $callback);
}
}
使用方法:
$data = [1, 2, 3, 4, 5];
$filter = new ArrayFilter($data);
$result = $filter->filter(function ($item) {
return $item % 2 === 0;
});
print_r($result);
为了更进一步解耦逻辑,我们可以把过滤条件封装成一个个“策略类”:
interface FilterStrategyInterface
{
public function apply($item): bool;
}
class EvenNumberFilter implements FilterStrategyInterface
{
public function apply($item): bool
{
return $item % 2 === 0;
}
}
然后修改 ArrayFilter 类来接收这个策略:
class StrategyArrayFilter
{
protected array $data;
public function __construct(array $data)
{
$this->data = $data;
}
public function filter(FilterStrategyInterface $strategy): array
{
return array_filter($this->data, [$strategy, 'apply']);
}
}
使用方法:
$data = [1, 2, 3, 4, 5];
$filter = new StrategyArrayFilter($data);
$result = $filter->filter(new EvenNumberFilter());
print_r($result);
这样,每种过滤逻辑都可以单独定义为一个类,实现良好的代码组织结构,便于测试和复用。
如果你希望更灵活地配置过滤器(比如根据配置文件选择策略),可以加入一个“工厂类”或“服务注册机制”。以下是一个简单的服务注册示例:
class FilterFactory
{
public static function create(string $type): FilterStrategyInterface
{
return match ($type) {
'even' => new EvenNumberFilter(),
default => throw new InvalidArgumentException("Unknown filter type: $type")
};
}
}
用法如下:
$filterType = 'even'; // 假设来自配置或用户输入
$strategy = FilterFactory::create($filterType);
$filter = new StrategyArrayFilter([1, 2, 3, 4, 5]);
$result = $filter->filter($strategy);
print_r($result);
通过将 array_filter() 的回调函数封装到类中,我们可以实现更清晰、更易测试和维护的代码结构。这种策略模式非常适合处理复杂或多变的过滤逻辑,特别是在大型应用中非常有用。