PHP 怎么PHP可信类型

wen PHP项目 1

本文目录导读:

PHP 怎么PHP可信类型

  1. 严格类型模式(declare(strict_types=1)
  2. 标量类型声明 (Scalar Type Declarations)
  3. 返回类型声明(Return Types)
  4. 联合类型(Union Types, PHP 8+)
  5. 类型注解与静态分析(PHPDoc + Psalm/phpstan)
  6. verify 辅助函数(运行时验证)
  7. Trusted Proxy(如果你指 Laravel)
  8. 总结:如何构建“可信类型”体系

在 PHP 中,“可信类型”(Trusted Types)通常指的是 PHP 的类型声明系统,特别是 严格类型模式(strict_types)类型注解,但如果你指的是 浏览器端的 Trusted Types API(用于防御 DOM XSS),那在 PHP 中主要是 输出编码安全上下文 的配合。

我假设你问的是 PHP 的类型安全机制,下面是详细解释:


严格类型模式(declare(strict_types=1)

这是 PHP 中最重要的“可信类型”机制,它决定了类型强制转换的严格程度。

默认(弱类型)模式:

<?php
function add(int $a, int $b): int {
    return $a + $b;
}
// 弱类型下,PHP 会尝试转换
echo add("5", 3); // 输出 8 (字符串 "5" 被强制转为 int)

严格模式:

<?php
declare(strict_types=1); // 必须在文件第一行
function add(int $a, int $b): int {
    return $a + $b;
}
// 严格模式下,类型不匹配会直接报 TypeError
// echo add("5", 3); // TypeError: Uncaught TypeError: add(): Argument #1 ($a) must be of type int, string given
echo add(5, 3); // 正常输出 8

关键点:

  • strict_types 必须在 调用方文件 的第一行声明,而不是在定义函数的文件。
  • 它只影响 标量类型(int, float, string, bool)。
  • 不会影响类、数组、可调用类型(这些本来就是强制的)。

标量类型声明 (Scalar Type Declarations)

PHP 7 引入了标量类型声明,配合 strict_types 使用:

<?php
declare(strict_types=1);
function process(
    int $num,
    float $price,
    string $name,
    bool $flag
): string {
    return "处理: $num, $price, $name, " . ($flag ? '真' : '假');
}

返回类型声明(Return Types)

确保函数返回特定类型:

<?php
declare(strict_types=1);
function fetchUser(int $id): ?array
{
    // 必须返回 array 或 null
    if ($id <= 0) {
        return null;
    }
    return ['id' => $id];
}

联合类型(Union Types, PHP 8+)

允许声明多个可能类型:

<?php
declare(strict_types=1);
function process(int|float|string $value): int|float
{
    // 根据类型做不同处理
    if (is_string($value)) {
        return strlen($value);
    }
    return $value * 2;
}

类型注解与静态分析(PHPDoc + Psalm/phpstan)

这是“可信类型”概念中 最实用的部分,通过 PHPDoc 注解让工具帮你做静态类型检查:

<?php
/**
 * 计算订单总价
 *
 * @param array<array{price: float, qty: int}> $items 商品列表
 * @param float $discount 折扣
 * @return float 折后总价
 *
 * @throws InvalidArgumentException 当价格或数量为负数时
 */
function calcTotal(array $items, float $discount): float
{
    $total = 0;
    foreach ($items as $item) {
        if ($item['price'] < 0 || $item['qty'] < 0) {
            throw new InvalidArgumentException('价格或数量不能为负数');
        }
        $total += $item['price'] * $item['qty'];
    }
    return $total * (1 - min(1, max(0, $discount)));
}

使用 PHPStanPsalm 来检查:

vendor/bin/phpstan analyse src --level=max

verify 辅助函数(运行时验证)

如果你需要更严格的运行时类型检查(不仅限于标量):

<?php
declare(strict_types=1);
class UserValidator
{
    public static function verifyArrayOfObjects(array $data, string $className): void
    {
        foreach ($data as $item) {
            if (!$item instanceof $className) {
                throw new TypeError("期望 {$className},收到 " . gettype($item));
            }
        }
    }
    public static function verifyEmail(string $email): void
    {
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            throw new InvalidArgumentException("无效的邮箱地址");
        }
    }
}

Trusted Proxy(如果你指 Laravel)

如果你在 Laravel 中使用 TrustedProxy,那是关于 HTTP 代理信任 的配置:

// config/trustedproxy.php
return [
    'proxies' => '*', // 信任所有代理
    'headers' => [
        Illuminate\Http\Request::HEADER_FORWARDED,
        Illuminate\Http\Request::HEADER_X_FORWARDED_FOR,
    ],
];

如何构建“可信类型”体系

<?php
declare(strict_types=1); // 1. 启用严格模式
class OrderService
{
    // 2. 明确的参数类型 + 联合类型
    public function createOrder(
        int $userId,
        int|float $amount,
        string $currency = 'CNY'
    ): Order {
        // 3. 运行时验证
        if ($amount <= 0) {
            throw new DomainException('金额必须大于0');
        }
        // 4. 返回值类型明确
        return new Order($userId, $amount, $currency);
    }
}
// 5. 静态分析工具(PHPStan/Psalm)保证未调用前就发现问题
// 6. 单元测试(PHPUnit)验证边界情况

推荐组合:

  • 开发期:PHPStan/Psalm(静态分析)+ strong typing
  • 运行期strict_types + 类型声明 + 自定义验证
  • 边界防御:框架的验证器(Laravel validation, Symfony Validator)

这样你就拥有了完整的“可信类型”保障,如果还有具体场景需要细化,可以告诉我。

抱歉,评论功能暂时关闭!