编程

7 个使用 PHP 8.5 的管道操作符的真实情景

14 2025-11-25 03:51:00

PHP 8.5 的管道符 (|>) 是一项功能强大的新增特性,它通过清晰简洁的方式实现操作链式调用,支持更具函数式编程风格的代码编写。它取左侧表达式的结果,并将其作为第一个参数传递给右侧的函数或方法。

$value = "hello world";

$result = $value
    |> function3(...)
    |> function2(...)
    |> function1(...);

本文将分享一些真实世界的例子,说明如何在 PHP 代码中使用管道运算符,使代码更清晰、更易读。

String cleanup in APIs

username 输入通常需要规范化。管道使该步骤可读。

$raw = "  John   Doe  ";

$username = $raw
    |> trim(...)
    |> strtolower(...)
    |> (fn($x) => preg_replace('/\s+/', '-', $x));

// Output: "john-doe"

如你所见,此处每一步都是专注的、可测试的转换:裁剪空格转换为小写将空格转换成横线

处理上传的 CSV 数据

在一个工作流中清理、验证行并将其映射到 DTO 中。

$rows = [
  ['name' => ' Widget A ', 'price' => '12.99', 'sku' => 'W-A'],
  ['name' => 'Widget B',   'price' => 'n/a',   'sku' => 'W-B'],   // invalid price
  ['name' => 'widget c',   'price' => '7.5',   'sku' => 'W-C'],
];

// normalizeRow might trim, cast price to float, unify casing:
// ['name' => 'Widget A', 'price' => 12.99, 'sku' => 'W-A']
// ['name' => 'Widget B', 'price' => null,  'sku' => 'W-B']
// ['name' => 'Widget C', 'price' => 7.5,   'sku' => 'W-C']

// isValidRow returns false if price is null or <= 0

$products = $rows
    |> (fn($xs) => array_map('normalizeRow', $xs))
    |> (fn($xs) => array_filter($xs, 'isValidRow'))
    |> (fn($xs) => array_map(Product::fromArray(...), $xs));

// Output: [Product('Widget A', 12.99, 'W-A'), Product('Widget C', 7.5, 'W-C')]

The chain expresses a pipeline: normalization, filtering, then construction.

HTTP 响应创建

将类中间件的转换组合,以生成最终响应体。

$data = ['msg' => 'hello', 'n' => 3];

$body = $data
    |> json_encode(...)
    |> (fn($x) => gzencode($x, 6))
    |> base64_encode(...);

// Output: H4sIAAAAAAAAA2WOuwrCMBBE…

每个可调用对象都是单个参数,从而形成一个紧凑的线性构建。

搜索查询准备

在将查询发送给搜索引擎之前,对查询进行净化和标记:

$query = "  Hello, WORLD!  ";

$tokens = $query
    |> trim(...)
    |> strtolower(...)
    |> (fn($x) => preg_replace('/[^\w\s]/', '', $x))
    |> (fn($x) => preg_split('/\s+/', $x))
    |> (fn($xs) => array_filter($xs, fn($t) => strlen($t) > 1));

// Output: ['hello', 'world']

该管道将混乱的输入转化为可供搜索的索引 token。

电商购物车合计

从有折扣和税费的项目中得出总计。

// Assume helpers:
// priceAfterDiscount(['price' => 100, 'discount' => 0.10]) -> 90.0
// applyTax(90.0) with 10% tax -> 99.0

$cartItems = [
  ['price' => 100, 'discount' => 0.10],
];

$total = $cartItems
    |> (fn($xs) => array_map('priceAfterDiscount', $xs))
    |> array_sum(...)
    |> (fn($sum) => applyTax($sum)); 
    // applyTax takes one argument

// Output: 99.0

步骤非常清晰:每项折扣合计税金;无需临时变量。

日志记录和指标充实

此管道使用时间戳、请求 ID 和 IP 充实事件,然后在记录日志之前编辑敏感字段。

$incomingEvent = [
    'user' => 'alice', 
    'email' => 'alice@example.com'
];

$event = $incomingEvent
    |> (fn($x) => array_merge($x, ['received_at' => 1696195560])) // e.g. time()
    |> (fn($x) => array_merge($x, ['request_id' => '9f2a1c0b7e3d4a56'])) // example random id
    |> (fn($x) => array_merge($x, ['ip' => '203.0.113.42'])) // example IP
    |> (fn($x) => redactSensitive($x)); // e.g. masks email

// Output:
/*
    [
        'user' => 'alice', 
        'email' => 'a***@example.com', 
        'received_at' => 1696195560, 
        'request_id' => '9f2a1c0b7e3d4a56', 
        'ip' => '203.0.113.42'
    ]
*/

图片处理链 (e.g., 缩略图)

在有些图片处理任务中,你可能需要加载图片,修改图片大小,添加水印,然后优化 web 实现。管道符可以帮你将此这些操作以清晰的方式表达出来。

$imagePath = '/images/source/beach.jpg';

$thumb = $imagePath
    // GD image resource from beach.jpg
    |> (fn($p) => imagecreatefromjpeg($p))
    // resized to 320×240   
    |> (fn($im) => resizeImage($im, 320, 240))
    // watermark added (e.g., bottom-right)
    |> (fn($im) => applyWatermark($im))
    // returns binary JPEG data or saved file path       
    |> (fn($im) => optimizeJpeg($im, 75));      

// Output: '/images/thumbs/beach_320x240_q75.jpg'

每一步都是一个单参数转换,返回下一个值,生成一个优化的缩略图。