调试 PHP 时谁都离不开变量打印——排查接口返回、看 ORM 关联数据、定位循环里某次迭代的数据不对。我见过太多项目用 var_dump / dd() 一把梭,输出像一团乱麻,嵌套一深就滚屏几页,关掉再开又得重新打印。Kint 把变量打印做成了可交互的可视化界面——能折叠的层级树、能搜索的内容、自动生成的取值代码,一行 d() 替代所有 if + echo。

Kint 由 kint-php 组织维护,主导维护者是 Jonathan Vollebregt,仓库 2012 年创建,到现在已经 13 年。
安装
composer require --dev kint-php/kint
官方推荐装到 --dev,毕竟调试工具不该进生产。要求 PHP >=7.4(v6.x),无任何 ext 依赖,纯 PHP 实现,MIT 协议。

最新稳定版 v6.1.0,2025 年 11 月发布,已经支持 PHP 8.5。Packagist 累计安装超过 2000 万次,345 个包依赖它。
基本用法
入口就一个函数 d(),传任意数量参数都能识别:
// 打印标量
d('hello', 42, 3.14, true, null);
// 打印数组
d($_SERVER);
// 打印对象(含 protected/private 属性)
d($request);
d($user, $order, $payment);
每次调用都会在输出顶部显示完整的调用位置(文件名+行号),方便定位是哪一次 dump。Kint::dump(...$args) 是等价写法。
需要纯文本(不依赖 JS,比如 CLI 或日志场景)用 s():
// Plain 模式:HTML 转义但不带折叠交互
s($complexObject);
CLI 环境下 Kint 自动检测(Kint::$cli_detection = true 默认开启),切换到带颜色和终端宽度自适应的 CliRenderer,不需要手动设置。
为什么 var_dump 不够用
立靶子再打。看下面这段:
$data = json_decode('{
"user": {
"name": "Bob",
"orders": [{"id": 1, "items": [{"sku": "A1", "price": 99}]}]
}
}', true);
var_dump($data);
输出是这种死板的纯文本:
array(1) {
["user"]=>
array(2) {
["name"]=>
string(3) "Bob"
["orders"]=>
array(1) {
...
问题:
- 嵌套一深缩进就乱,对齐靠肉眼
- 不知道取某个深层值的 PHP 代码怎么写(要自己脑补
$data['user']['orders'][0]['items'][0]['price']) - 数组里的对象有循环引用直接溢出
- 没法搜索某个 key 在哪一层
- 关了终端就没了,下次还得重 dump
我之前以为 Laravel 自带的 dd()(Symfony VarDumper)已经够好了,直到遇到一个 50 层嵌套的 API 响应——dd() 也只是把 var_dump 美化了一下,根本问题没解决。
富文本交互:折叠、搜索、Access Path
Kint 在浏览器里输出的是一套完整的 JS 交互界面(RichRenderer)。

操作上和 IDE 的变量视图很像:
- 点击任意节点展开/折叠
-
双击
+展开所有子节点 -
按
d切换键盘导航模式 -
按
a显示 Access Path -
按
s打开实时搜索框 -
按
f把当前 dump 移到底部 docked folder
Access Path 是 Kint 区别于其他调试工具的杀手级特性——它会自动告诉你取到这个值应该怎么写代码。深层数组里的某个字段,鼠标 hover 上去直接显示:
$data['user']['orders'][0]['items'][0]['price']
不需要自己数层数和写 key,直接复制粘贴就能用。调试复杂 API 响应或 ORM 实体关联时省下来的时间不是一点半点。
我判断这是 Kint 最值钱的功能,没有之一。
修饰符:5 个符号精确控制输出
在 d 前面加一个符号就能改变行为:
// + 无深度限制(默认 7 层就截断)
+d($deepObject);
// ! 自动展开(不折叠直接铺开)
!d($request);
// ~ 纯文本模式(强制 TextRenderer,适合 grep 管道)
~d($log);
// - 先 ob_end_clean 清空所有输出缓冲,dump 后 flush(排查 OB 嵌套问题用)
-d($var);
// @ 返回字符串而不直接输出
$log = @d($var);
修饰符也能组合,比如 ~+d($var) 就是"纯文本+无深度限制",输出到文件再 grep。
注意 +d() 是双刃剑。dump 一个 ORM 实体或 DI 容器(比如 Laravel 的 Application 实例)时,无深度限制会输出几十 MB 的 HTML,浏览器直接卡死。官方文档首页就警告了,但每年还是有一堆人踩。
MicrotimePlugin:一行代码做性能打点
Kint 内置了 30+ 插件,自动识别常见数据类型——JSON 字符串会被解析成可展开结构,Base64 会被解码,9-10 位整数会被识别成时间戳,颜色字符串会附带色板,XML 会被解析成树。其中我日常用得最多的是 MicrotimePlugin。
把 microtime() 传给 d(),会自动显示距离上次 dump 的时间差、内存占用、dump 次数:
// 在代码关键节点打点
d(microtime());
$users = $repo->findActiveUsers(); // 数据库查询
d(microtime());
$result = $apiClient->fetchDetails(); // 远程接口
d(microtime());
$rendered = $twig->render('page.html', $data); // 模板渲染
d(microtime());
每次 dump 的输出会带上:
Lap: 0.234s Total: 1.567s Memory: 24.5 MB Count: 3
定位"哪段代码慢"不用上 Xdebug,几行 d(microtime()) 就能初步定位瓶颈在哪一段。需要重置计数器调用 Kint\Parser\MicrotimePlugin::clean()。
配置和生产环境关闭
Kint 默认开启,生产环境必须关。两种方式:
// 方式 1:全局关闭
Kint\Kint::$enabled_mode = false;
// 方式 2:按 IP 开启(官方推荐)
Kint\Kint::$enabled_mode = ($_SERVER['REMOTE_ADDR'] ?? '') === '你的IP';
其他常用配置:
Kint\Kint::$depth_limit = 7; // 最大解析深度
Kint\Kint::$display_called_from = true; // 显示调用位置
Kint\Kint::$expanded = false; // 默认是否展开
// 主题切换(5 个内置主题)
Kint\Renderer\RichRenderer::$theme = 'solarized-dark.css';
// 可选:original.css / solarized.css / solarized-dark.css / aante-light.css / aante-dark.css
// 屏蔽敏感类(按完整类名,不按字段名)
Kint\Parser\BlacklistPlugin::$blacklist[] = App\Service\SensitiveService::class;
BlacklistPlugin 默认就把 PSR Container 和 EventDispatcher 加进了浅黑名单(直接 dump 时显示,嵌套时不展开),防止 dump 一个 Service 容器时把整个应用全展开。
如果项目用 CSP(Content Security Policy),Kint 支持 nonce:
Kint\Renderer\AbstractRenderer::$js_nonce = $cspNonce;
Kint\Renderer\AbstractRenderer::$css_nonce = $cspNonce;
框架集成
CodeIgniter4 内置 Kint,开箱即用,无需配置。
Laravel 共存无冲突。Laravel 自带 Symfony VarDumper 的 dd() 和 dump(),而 Kint 没有内置 dd()(只有 d() 和 s()),所以两者可以共存——要用 Kint 就调 d(),要用 Laravel 自带的就调 dd()。
Twig 模板装 kint-php/kint-twig 后可以在模板里用:
{{ d(user) }}
{{ s(order) }}
不过我个人的习惯是模板里别调试,逻辑都回到 PHP 里再 dump,模板层只负责渲染。
需要注意的坑
dd() 不是内置函数。 很多人(包括我之前)以为 Kint 有 dd(),其实只有 d() 和 s()。CodeIgniter4 自己实现了 dd()(dump 后 exit),Symfony VarDumper 也有自己的 dd()。需要 dump-and-die 行为的话,自己写一行 d($var); exit;,或者装 kint-php/kint-helpers。
+d() 会让浏览器卡死。 默认深度限制是 7,加上 + 后无限展开。dump ORM 实体、DI 容器、大型 Collection 时输出可能上百 MB,浏览器直接冻住。要排查这种结构用 ~+d($var)(纯文本+无限制),把输出重定向到文件再 grep。
生产环境忘关等于数据泄露。 Kint 默认 $enabled_mode = true,会把完整对象结构(含 protected/private 属性)打印到页面。上线前必须显式关闭或按 IP 限制,否则敏感字段(DB 密码、API key)随时可能暴露。
raveren/kint 是废弃包。 Packagist 上的 raveren/kint 是原作者 Rokas Šleinius 的旧版(v1.x,PHP 5.1+),已标记 abandoned。要用就装 kint-php/kint(v6.x,PHP 7.4+)。这段历史还有点戏剧——原作者声称 Kint 被恶意贡献者"偷走"了,于是 fork 出来一个叫 Sage 的分支。两边恩怨不评价,但代码层面 kint-php/kint 是当前活跃维护的版本。
v6.0 升级要重写自定义插件。 2024 年 11 月发布的 v6.0 重做了插件系统,从 v5 升级时如果有自定义插件,需要按新插件接口移植。性能换来的:v6 比 v5 快 33%,内存少 30%。
它依然值得用
Kint 累计下载量超过 2000 万次,最新 v6.1.0 在 2025 年 11 月发布,支持到 PHP 8.5,345 个包依赖它,CodeIgniter4 在内的项目直接内置它作为调试工具——这种成熟度的库,没必要再去找替代品。Symfony VarDumper(Laravel 默认)是合理选择,但缺 Access Path 和富文本交互这两个核心特性,调试复杂结构时效率差一截。我的判断是:任何 PHP 项目在 dev 依赖里加上 kint-php/kint,调试体验立竿见影。
原文标题: [kint-php/kint]带折叠和 Access Path 的 PHP 调试输出库
原文地址: https://phpreturn.com/index/a6a2e55647cb53.html
原文平台: PHP武器库
版权声明: 本文由phpreturn.com(PHP武器库官网)原创和首发,所有权利归phpreturn(PHP武器库)所有,本站允许任何形式的转载/引用文章,但必须同时注明出处。