当前位置:首页>php>别再手写 URL 解析器了 PHP 8.5 URI 扩展让 URL 处理更安全、更干净

别再手写 URL 解析器了 PHP 8.5 URI 扩展让 URL 处理更安全、更干净

  • 2026-01-27 04:22:43
别再手写 URL 解析器了 PHP 8.5 URI 扩展让 URL 处理更安全、更干净

parse_url() 能用,但不够用

多年来,PHP 开发者处理 URL 的方式大同小异:

  • • 用 parse_url() 拆分各部分
  • • 用 rawurlencode() / urlencode() 转义
  • • 用字符串拼接重建最终 URL
  • • 遇到"奇怪"输入时,再上几个正则

大多数情况下这套流程能跑通。问题在于,URL 处理恰恰是那种"在边角情况下出问题"的领域:编码、fragment、userinfo、国际化域名、"等价但不相同"的 URL,以及各种只在生产日志里才冒出来的边缘场景。

PHP 8.5 提供了一个内置替代方案:一个始终可用的 URI 扩展,提供 API 来按照 RFC 3986 和 WHATWG URL 标准解析、修改 URL/URI。

如果"标准"二字让你觉得抽象,这里给出实际含义:

  • • 拿到 URI/URL 对象,而不是数组 + 字符串拼接。
  • • 用安全的组件 getter 和不可变的 with*() 方法。
  • • 你可以选择 RFC 3986 行为(严格 URI,"原始 vs 规范化解码")或浏览器风格的 WHATWG 行为(Unicode/IDNA、软错误、自动编码)。

本文是一篇实战教程,重点讲:

  • • 为什么手动解析容易出错,
  • • 新 URI 对象怎么用,
  • • 如何安全地修改/规范化,
  • • 在重定向、签名链接等安全敏感场景下如何使用。

不讲升级指南,不讲废弃清单——只讲 URI 扩展。

手动 URL 解析的问题

parse_url() 不解码(而且很容易忘)

PHP 的 parse_url() 返回各组件,但不会 URL 解码它们。

也就是说:

$u = parse_url("https://example.com/t%65st?name=Ali%63e#fr%61g");
var_dump($u['path']);   // "/t%65st"
var_dump($u['query']);  // "name=Ali%63e"
var_dump($u['fragment']); // "fr%61g"

如果你在比较路径或应用路由规则时没有统一解码/规范化,可能会把等价的 URI 当成不同的来处理。

更糟的是:团队往往混用:

  • • 有些地方用解码后的值,
  • • 有些地方用原始值,
  • • 再加上散落在各处的临时解码逻辑。

这种混乱很容易埋下隐蔽 bug 和安全隐患。

字符串拼接容易拼出"差一点对"的 URL

手动重建 URL 容易犯的错:

  • • 漏掉 ? 或 #
  • • 重复编码
  • • 完全没编码
  • • 编码错了东西(比如把整个 query string 编码而不是只编码 value)
  • • 丢失或打乱参数顺序
  • • 空 query/fragment 处理不当

一个常见的"差一点对"函数:

function addQueryParam(string $url, string $key, string $value): string
{
    $parts = parse_url($url);
    $query = $parts['query'] ?? '';
    $query .= ($query === '' ? '' : '&') . $key . '=' . urlencode($value);
    $out = $parts['scheme'] . '://' . $parts['host'] . ($parts['path'] ?? '');
    if ($query !== '') {
        $out .= '?' . $query;
    }
    if (isset($parts['fragment'])) {
        $out .= '#' . $parts['fragment'];
    }
    return $out;
}

看起来没问题。直到遇到:

  • • 没有 scheme/host 的 URL(相对 URL),
  • • 带 userinfo/port 的 URL,
  • • 已经编码过的值,
  • • 需要 rawurlencode() 规则(RFC 3986)的参数,
  • • 应该原样保留的 fragment。

等价的 URL 不一定是相同的字符串

下面这些可以指向同一个资源,但字符串不同:

  • • scheme/host 大小写不同(HTTPS://EXAMPLE.com
  • • path 中 %65 vs e/t%65st vs /test
  • • path 中的点号段(/foo/../bar/
  • • 默认端口(https 的 :443

如果你把 URL 当成纯字符串处理,要么:

  • • 缓存/路由出现诡异问题,
  • • 要么安全检查被绕过,因为你比较的是"错误的表示形式"。

IDNA(国际化域名)还涉及安全问题

如果你允许用户提交 URL,国际化域名可能是合法的——但也可能造成混淆。域名可以用 Unicode 或 punycode(ASCII 形式)表示。RFC 讨论中明确指出人为风险:punycode 域名在 Unicode 渲染时可能看起来像一个熟悉的、但实际不同的域名。

这不是你想用正则"手动处理"然后祈祷没问题的事。

URI 扩展的概念:URI 对象 + 两套标准

PHP 8.5 的 URI 扩展提供两个主要类:

  • • Uri\Rfc3986\Uri(RFC 3986 合规,严格 URI 规则)
  • • Uri\WhatWg\Url(WHATWG URL 合规,浏览器风格的 URL 规则)

配套的类型包括:

  • • Uri\InvalidUriException
  • • Uri\WhatWg\InvalidUrlException
  • • Uri\WhatWg\UrlValidationError 和 UrlValidationErrorType
  • • Uri\UriComparisonMode(用于比较)

一个关键设计决策:两个实现都是 readonly 且以不可变方式使用——withPath()withQuery() 等方法返回新实例。

另一个要点:这个扩展在 PHP 8.5 中始终可用,底层由以下库驱动:

  • • uriparser(用于 RFC 3986)
  • • Lexbor(用于 WHATWG URL)

所以你不需要第三方库就能获得合理的 URL 处理能力。

创建和解析 URI:从字符串到组件

最简单的情况:解析一个 HTTP URL 并访问各部分

RFC 3986:

use Uri\Rfc3986\Uri;

$uri = new Uri("https://php.net/releases/8.5/en.php");

echo $uri->getScheme(); // "https"
echo $uri->getHost();   // "php.net"
echo $uri->getPath();   // "/releases/8.5/en.php"

WHATWG:

use Uri\WhatWg\Url;

$url = new Url("https://example.com/path?query=1#frag");

echo $url->getScheme();      // "https"
echo $url->getAsciiHost();   // "example.com"
echo $url->getPath();        // "/path"
echo $url->getQuery();       // "query=1"
echo $url->getFragment();    // "frag"

注意:WHATWG 的 getter 故意不返回分隔符(如 :/?#)。

构造函数抛异常;parse() 返回 null

两个实现都支持两种解析风格:

  • • 构造函数:无效时抛异常
  • • parse():无效时返回 null

RFC 3986 行为:

use Uri\Rfc3986\Uri;
use Uri\InvalidUriException;

try {
    $uri = new Uri("not a uri");
} catch (InvalidUriException $e) {
    // 拒绝输入
}

$uri = Uri::parse("not a uri");
var_dump($uri); // null

WHATWG 行为提供更丰富的错误信息:

use Uri\WhatWg\Url;
use Uri\WhatWg\InvalidUrlException;

try {
    $url = new Url("invalid url");
} catch (InvalidUrlException $e) {
    // $e->errors 包含 UrlValidationError 实例
}

$errors = [];
$url = Url::parse("invalid url", null, $errors);
var_dump($url);    // null
var_dump($errors); // UrlValidationError 数组

这种区分(硬错误 vs 软错误 vs parse-and-return-null)在 RFC 中有详细说明。

Base URL 和引用解析(相对 → 绝对)

有了这个功能,你不再需要手动检查是否以 / 开头然后拼接。

在构造函数或 parse() 中使用 base URL:

use Uri\Rfc3986\Uri;

$base = new Uri("https://example.com");
$uri  = new Uri("/foo", $base);

echo $uri->toString(); // "https://example.com/foo"

WHATWG 类似:

use Uri\WhatWg\Url;

$base = new Url("https://example.com");
$url  = Url::parse("/foo", $base);

echo $url->toAsciiString(); // "https://example.com/foo"

扩展还提供了便捷的 resolve() 方法,以当前对象作为 base。

安全修改:设置/替换 path、query、fragment(不可变)

拿到对象后,可以用 with*() 方法修改组件。这些方法返回新实例,原对象保持不变。

RFC 3986:withPath()、withQuery()、withFragment()

use Uri\Rfc3986\Uri;

$uri = new Uri("https://example.com/products?sort=asc#top");

$updated = $uri
    ->withPath("/products/123")
    ->withQuery("sort=desc&ref=home")
    ->withFragment("reviews");

echo $uri->toString();     // 原对象不变
echo $updated->toString(); // 修改后的

RFC 3986 提供"原始"和"规范化解码"两种 getter(下一节详述),以及 toString() 和 toRawString() 方法。

WHATWG:同样的思路,外加 ASCII/Unicode 字符串输出

use Uri\WhatWg\Url;

$url = new Url("https://example.com/");

$new = $url
    ->withPath("/search")
    ->withQuery("q=php+8.5")
    ->withFragment("results");

echo $new->toAsciiString();
echo $new->toUnicodeString();

WHATWG 有 toAsciiString() 和 toUnicodeString() 两种输出,分别用于机器处理和人类展示。

一个小但重要的行为:输入中的分隔符

使用 WHATWG 时,如果你在设置 query/fragment 时不小心包含了 ? 或 #,它会把它们当作分隔符并去掉:

use Uri\WhatWg\Url;

$url = new Url("https://example.com/");
$url = $url->withQuery("?foo");
$url = $url->withFragment("#bar");

echo $url->getQuery();    // "foo"
echo $url->getFragment(); // "bar"

这个行为在文档中有明确说明。

规范化与编码:避免重复编码和"奇怪字符"

URI 扩展的价值不止于 API 设计——它让你能控制 URL 的表示形式。

RFC 3986 给你两种表示:原始 vs 规范化解码

对于大多数组件,Uri\Rfc3986\Uri 暴露:

  • • raw:解析器给出的形式(最接近原始输入)
  • • 规范化解码:规范化 + 百分号解码,意在成为规范形式且可往返转换

RFC 解释了为什么需要两种形式以及何时使用——签名方和 API 客户端通常偏好 raw,而路由/缓存通常偏好规范化解码。

具体效果:

use Uri\Rfc3986\Uri;

$uri = new Uri("https://%61pple:p%61ss@ex%61mple.com:433/foob%61r?%61bc=%61bc#%61bc");

echo $uri->getRawHost(); // "ex%61mple.com"
echo $uri->getHost();    // "example.com"

echo $uri->getRawPath(); // "/foob%61r"
echo $uri->getPath();    // "/foobar"

echo $uri->getRawQuery(); // "%61bc=%61bc"
echo $uri->getQuery();    // "abc=abc"

规范化示例:

use Uri\Rfc3986\Uri;

$uri = new Uri("HTTPS://EXAMPLE.COM/foo/../bar/");

echo $uri->getRawScheme(); // "HTTPS"
echo $uri->getScheme();    // "https"

echo $uri->getRawHost(); // "EXAMPLE.COM"
echo $uri->getHost();    // "example.com"

echo $uri->getRawPath(); // "/foo/../bar/"
echo $uri->getPath();    // "/bar/"

WHATWG 在修改时自动编码某些字符

如果你设置的 path 包含该组件必须百分号编码的字符,WHATWG 会自动编码:

use Uri\WhatWg\Url;

$url = new Url("https://example.com");
$url = $url->withPath("/?#:");

echo $url->getPath(); // "/%3F%23:"

这能防止意外构建出损坏的 URL。

"重复编码"陷阱(以及新 API 如何帮忙)

重复编码通常这样发生:

  1. 1. 你用 rawurlencode() 编码一个值,因为"它要放进 URL"
  2. 2. 你手动把它加到 query string
  3. 3. 后来某处又编码了一次(框架、代理、客户端)

使用 URI 对象,一个好做法是:

  • • 数据保持为普通字符串(未编码)
  • • 用 http_build_query() 构建 query(或你偏好的编码器)
  • • 把结果传给 withQuery()

示例:

use Uri\Rfc3986\Uri;

$base = new Uri("https://example.com/search");

$params = [
    'q' => 'php 8.5 uri',
    'tag' => 'url/encoding',
];

// RFC 3986 风格编码(空格用 %20 而非 +)
$query = str_replace('+', '%20', http_build_query($params));

$uri = $base->withQuery($query);
echo $uri->toString();

http_build_query() 不一定适合所有场景,但好处是编码规则集中在一处,而非散落在各种字符串拼接里。

如果确实需要对 path 段进行 RFC 3986 原始编码,PHP 的 rawurlencode() 遵循 RFC 3986 规则。

验证用户输入的 URL:实用的最低规则

如果输入来自用户(或不可信来源),验证应该有明确的立场。

对于你打算 fetch 或跳转的 URL,一个务实的安全导向模式:

  • • 必须解析成功(硬错误直接拒绝)
  • • 只允许 http / https
  • • URL 中不能有用户名/密码
  • • 域名白名单(用 ASCII 形式比较)
  • • 可选:限制端口
  • • 可选:要求绝对 URL(或相对 URL 基于已知 base 解析)

严格验证 helper(WHATWG 版本)

WHATWG 适合处理"浏览器风格"URL 和 IDNA。

use Uri\WhatWg\Url;
use Uri\WhatWg\InvalidUrlException;

function validateExternalUrl(string $input, array $allowedHosts): Url
{
    try {
        $softErrors = [];
        $url = new Url($input, null, $softErrors);
    } catch (InvalidUrlException $e) {
        throw new InvalidArgumentException("Invalid URL.");
    }

    // Scheme 白名单
    $scheme = $url->getScheme();
    if (!in_array($scheme, ['http', 'https'], true)) {
        throw new InvalidArgumentException("Unsupported scheme.");
    }

    // 禁止凭证
    if ($url->getUsername() !== null || $url->getPassword() !== null) {
        throw new InvalidArgumentException("Credentials in URL are not allowed.");
    }

    // Host 白名单(ASCII 比较)
    $host = $url->getAsciiHost();
    if ($host === null || !in_array(strtolower($host), $allowedHosts, true)) {
        throw new InvalidArgumentException("Host not allowed.");
    }

    // 可选:端口限制
    $port = $url->getPort();
    if ($port !== null && !in_array($port, [80, 443], true)) {
        throw new InvalidArgumentException("Port not allowed.");
    }

    return $url;
}

几点说明:

  • • Url 即使解析成功也可能返回软错误。RFC 解释了"软 vs 硬"模型,并给出了解析继续但报告验证错误的例子。
  • • WHATWG 同时暴露 getAsciiHost() 和 getUnicodeHost();比较通常用 ASCII,展示用 Unicode。

RFC 3986 验证:严格 URI 解析 + 规范化选项

如果你在验证通用 URI(不只是 HTTP URL),或者你关心 raw vs 规范化解码的表示,Uri\Rfc3986\Uri 是个好选择。

use Uri\Rfc3986\Uri;
use Uri\InvalidUriException;

function validateHttpUri(string $input, array $allowedHosts): Uri
{
    try {
        $uri = new Uri($input);
    } catch (InvalidUriException $e) {
        throw new InvalidArgumentException("Invalid URI.");
    }

    $scheme = $uri->getScheme();
    if (!in_array($scheme, ['http', 'https'], true)) {
        throw new InvalidArgumentException("Unsupported scheme.");
    }

    // Userinfo 在大多数 Web 应用中是个坑
    if ($uri->getUserInfo() !== null) {
        throw new InvalidArgumentException("Userinfo is not allowed.");
    }

    $host = $uri->getHost();
    if ($host === null || !in_array(strtolower($host), $allowedHosts, true)) {
        throw new InvalidArgumentException("Host not allowed.");
    }

    return $uri;
}

实际用例:签名链接、安全重定向、规范 URL

用例:签名链接而不破坏编码

签名 URL(HMAC token、临时访问链接、CDN 认证)对表示形式极其敏感。一个小的"规范化变更"就能使签名失效。

这也是 RFC 明确指出"API 客户端或签名方"通常偏好原始表示的原因。

一个简单的签名 URL 方法:

  1. 1. 构建 URL
  2. 2. 对稳定的字符串表示计算签名
  3. 3. 把签名作为 query 参数加进去

示例,使用 RFC 3986 和 toRawString() 签名:

use Uri\Rfc3986\Uri;

function signUri(Uri $uri, string $secret): Uri
{
    // 当你想避免意外转换时,用 raw string
    $baseString = $uri->toRawString();
    $sig = hash_hmac('sha256', $baseString, $secret);

    $query = $uri->getRawQuery();
    $query = $query ? $query . '&' : '';
    $query .= 'sig=' . rawurlencode($sig);

    return $uri->withQuery($query);
}

$uri = new Uri("https://download.example.com/file/%2Fsafe?expires=1736035200");
$signed = signUri($uri, "super-secret-key");

echo $signed->toRawString();

两个要点:

  • • 你是故意选择 raw 的,因为签名关心的是"线上实际发送的是什么"。
  • • query 构建仍然要小心,避免编码错误。

如果你的签名算法需要规范形式(有些确实需要),可以故意对 toString() 签名——但要知道自己在做什么,而不是意外这么做。

用例:安全重定向(避免开放重定向 + 解析混淆)

安全重定向问题通常长这样:

  1. 1. 你有 /login?next=<something>
  2. 2. 登录后跳转到 next
  3. 3. 攻击者尝试 next=https://evil.com 或各种变体

一个健壮的模式是:

  1. 1. 把用户输入解析为相对 URL 或绝对 URL
  2. 2. 相对 URL 基于你自己的已知 base 解析
  3. 3. 验证 host/scheme 是你的(或在允许列表中)

使用 WHATWG:

use Uri\WhatWg\Url;

function safeRedirectTarget(string $next, string $appBase): string
{
    $base = new Url($appBase);

    // 安全解析相对引用
    $errors = [];
    $resolved = Url::parse($next, $base, $errors);

    if ($resolved === null) {
        return $base->toAsciiString(); // fallback
    }

    // 只允许同 host
    if (strtolower($resolved->getAsciiHost() ?? '') !== strtolower($base->getAsciiHost() ?? '')) {
        return $base->toAsciiString();
    }

    // 只允许 http/https
    if (!in_array($resolved->getScheme(), ['http', 'https'], true)) {
        return $base->toAsciiString();
    }

    return $resolved->toAsciiString();
}

echo safeRedirectTarget("/dashboard", "https://app.example.com");

这里用到了 base URL 解析和引用解析功能。

用例:规范 URL(SEO 和缓存的一致表示)

规范化通常意味着:

  • • scheme/host 小写
  • • 移除 path 中的点号段
  • • 移除默认端口
  • • query 保持一致(有时排序)
  • • 决定如何处理末尾斜杠

使用 Uri\Rfc3986\Uri,你已经可以通过 get*() vs getRaw*()(以及 toString() vs toRawString())清晰地获得规范化行为。

一个简单的规范化示例:

use Uri\Rfc3986\Uri;

function canonicalizeForCache(Uri $uri): Uri
{
    // 从规范化解码的部分开始
    $uri = $uri
        ->withScheme($uri->getScheme())
        ->withHost($uri->getHost())
        ->withPath($uri->getPath());

    // 为缓存 key 排序 query 参数(这是一种策略选择)
    $query = $uri->getQuery();
    if ($query) {
        parse_str($query, $params);
        ksort($params);
        $sorted = http_build_query($params, '', '&', PHP_QUERY_RFC3986);
        $uri = $uri->withQuery($sorted);
    }

    return $uri;
}

$u = new Uri("HTTPS://EXAMPLE.COM/foo/../bar/?b=2&a=1");
echo canonicalizeForCache($u)->toString();

这个函数不试图覆盖所有规范化策略(那是应用层面的事),但结构化 API 的好处是:规则可以显式构建、可以测试。

从 parse_url() + 字符串拼接迁移(不痛苦)

你不需要一次性重写所有代码。最简单的迁移路径是:

1. 找出 URL 处理对安全敏感或容易出 bug 的地方:

  • • 重定向
  • • webhook 验证
  • • 签名 URL
  • • 域名白名单
  • • 路由/缓存 key

2. 先替换这些。

3. 纯展示用途的简单解析,等到有必要时再处理。

迁移前:数组解析 + 手动重建

$parts = parse_url($input);
$host  = $parts['host'] ?? null;

if ($host !== 'example.com') {
    throw new Exception("Bad host");
}

$newUrl = $parts['scheme'] . '://' . $parts['host'] . '/new-path';

问题:

  • • 没处理 port、userinfo、fragment、相对 URL
  • • 没有规范化
  • • 没有规范化选择
  • • 容易构建出无效输出

迁移后:使用 Url/Uri,改动局部化

use Uri\WhatWg\Url;

$url = new Url($input);

if (strtolower($url->getAsciiHost() ?? '') !== 'example.com') {
    throw new InvalidArgumentException("Bad host");
}

$new = $url->withPath('/new-path');
echo $new->toAsciiString();

代码更短,意图更明确,细节上更难出错。

RFC 3986 和 WHATWG 怎么选(经验法则)

使用 Uri\WhatWg\Url 当:

  • • 你在处理来自浏览器/用户的 HTTP(S) URL
  • • 你需要 IDNA/Unicode 域名处理(getUnicodeHost() 用于展示,getAsciiHost() 用于比较)
  • • 你想要 WHATWG 解析行为和错误报告(软错误)

使用 Uri\Rfc3986\Uri 当:

  • • 你在处理"Web URL"之外的通用 URI
  • • 你需要 raw vs 规范化解码的表示
  • • 你在做签名或协议层面的工作,表示形式很重要

RFC 明确区分了这两种方法,包括 Unicode/IDNA 支持的差异。

附加内容:正确比较 URL(equals() 以及为什么没有 __toString())

一个值得留意的设计:内置 URI 类故意不实现 __toString(),因为松散比较(==)容易出错。

取而代之,你用 equals() 比较:

use Uri\Rfc3986\Uri;
use Uri\UriComparisonMode;

$u1 = new Uri("https://example.COM#foo");
$u2 = new Uri("https://EXAMPLE.COM");

var_dump($u1->equals($u2)); // true
var_dump($u1->equals($u2, UriComparisonMode::IncludeFragment)); // false

WHATWG 类似:

use Uri\WhatWg\Url;
use Uri\UriComparisonMode;

$a = new Url("https:////example.COM/");
$b = new Url("https://EXAMPLE.COM");

var_dump($a->equals($b)); // true

结论

PHP 8.5 的 URI 扩展看起来是个小功能,用一段时间后才会发现它挡掉了多少细微的 URL bug。

核心价值在于控制

  • • 你可以选择 RFC 3986 vs WHATWG 语义。
  • • 你可以决定要 raw 还是规范化解码的表示。
  • • 你可以不可变且安全地修改组件。
  • • 你可以用更难意外削弱的方式验证和比较 URL。

如果你曾经发布过一个"快速 URL 修复",后来在安全报告或生产事故中看到它,这个扩展值得尽早采用——从重定向和签名 URL 开始。

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-02-08 09:20:38 HTTP/2.0 GET : https://f.mffb.com.cn/a/464174.html
  2. 运行时间 : 0.095909s [ 吞吐率:10.43req/s ] 内存消耗:4,609.78kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=2990f1769ddfb2d0b245007918612d8e
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000544s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000688s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000303s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000710s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000512s ]
  6. SELECT * FROM `set` [ RunTime:0.000224s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000634s ]
  8. SELECT * FROM `article` WHERE `id` = 464174 LIMIT 1 [ RunTime:0.000744s ]
  9. UPDATE `article` SET `lasttime` = 1770513638 WHERE `id` = 464174 [ RunTime:0.001853s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 64 LIMIT 1 [ RunTime:0.000308s ]
  11. SELECT * FROM `article` WHERE `id` < 464174 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.005695s ]
  12. SELECT * FROM `article` WHERE `id` > 464174 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.003965s ]
  13. SELECT * FROM `article` WHERE `id` < 464174 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.002378s ]
  14. SELECT * FROM `article` WHERE `id` < 464174 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.001329s ]
  15. SELECT * FROM `article` WHERE `id` < 464174 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.003828s ]
0.097594s