Announcement

👇Official Account👇

Welcome to join the group & private message

Article first/tail QR code

Skip to content

Mago 1.0.0 深度解析:Rust 重写 PHP 工具链,31 倍提速背后的生产级实战

2026 年,Rust 正在以不可逆转的势头改写各语言的工具链生态:uv 替代 pip、ruff 替代 flake8、Polars 替代 Pandas。现在,这股浪潮终于涌到了 PHP。

经过 1000+ 次提交、13 个 RC 版、34 个 Beta 版和 12 个 Alpha 版的打磨,Mago 1.0.0 正式发布——一个用 Rust 编写的 PHP 静态分析器、Linter 和 Formatter 三合一工具链,单个二进制文件,无需 PHP 运行时。

一、为什么 PHP 需要 Mago?

1.1 现有工具链的痛点

工具功能WordPress 全库分析时间问题
PHPStan静态分析120.35s启动慢,level 8 假阳性多
Psalm静态分析45.53s内存占用大,泛型推断有限
PHP-CS-Fixer格式化/lint25.3s配置复杂,规则冲突多
Phan静态分析66.4s维护停滞,社区萎缩

这些工具的核心瓶颈是同一个:它们都是用 PHP 写的。PHP 作为动态语言,在做 AST 解析、类型推断、跨文件分析这类重 CPU 计算时天然受限。每次运行 PHPStan,你都要等 PHP 解释器启动、加载 Composer 依赖、解析 AST、做类型推断——每一层都有 overhead。

1.2 Mago 的性能突破

Mago vs 同类工具(WordPress 全库基准测试):
  静态分析:Mago 1.46s vs Phan 66.4s vs PHPStan 55.9s → 45 倍提速
  Lint:    Mago 0.88s vs PHP-CS-Fixer 25.3s → 29 倍提速
  Format:  Mago 0.43s vs PrettyPHP 24.3s → 56 倍提速

完整分析(analyze + lint + format):
  Mago:    3.88s
  PHPStan: 120.35s → Mago 快 31 倍
  Psalm:   45.53s → Mago 快 12 倍

31 倍的提速意味着什么?以前需要等 2 分钟才能完成的分析,现在 3 秒就出结果。你可以在每次保存文件时运行 Mago,获得即时反馈,而不是等到 CI 阶段才发现问题。

二、Mago 三大核心功能详解

2.1 Analyzer(静态分析)

Mago 1.0.0 的静态分析器经过了完整重写,支持:

  • 深度类型推断:泛型、条件类型、流向收窄(flow narrowing)
  • 控制流分析:检测 unreachable code、变量未初始化使用
  • 兼容 Psalm/PHPStan 注解@param@return@var@template
  • 属性初始化检查:确保构造函数中所有属性都被初始化
  • 异常跟踪@throws 验证,追踪异常传播路径
  • 插件系统:可扩展的类型提供器(Type Provider),支持框架特定的类型推断
php
// Mago 能检测的类型推断场景
class UserService {
    /** @param int|string $id */
    public function find($id): ?User {
        // Mago 知道 $id 是 int|string
        if (is_int($id)) {
            // 流向收窄:这里 $id 是 int
            return $this->repository->findById($id);
        }
        // 这里 $id 是 string
        return $this->repository->findByName($id);
    }

    public function delete(User $user): void {
        // Mago 检测:如果 $user 是 null,这里是类型错误
        $this->repository->delete($user);
    }
}

2.2 Linter(代码检查)

135 条 lint 规则,分布在 9 个类别:

类别重点示例规则
最佳实践惯用 PHP 模式禁止在循环中创建闭包
清晰度代码可读性禁止嵌套三元表达式
一致性统一编码风格禁止混用 array()[]
正确性逻辑错误检测 == 应为 === 的场景
弃用过时模式检测 create_function() 使用
可维护性长期健康检测过长的方法
冗余不必要代码检测无用的 else 分支
安全性null 处理检测未检查的 null 返回值
安全安全漏洞检测 eval() 使用

许多规则支持自动修复

bash
# 自动修复所有可修复的 lint 问题
mago lint --fix

# 只检查特定类别
mago lint --only=correctness,safety

# 生成 baseline(忽略现有问题,只防止新问题)
mago lint --generate-baseline
mago lint --baseline=.mago-baseline.json

2.3 Formatter(格式化)

确定性格式化器,遵循 PER-CS(PHP-FIG 扩展推荐编码标准),50+ 自定义选项:

toml
# mago.toml — 格式化配置
[format]
print_width = 120
indent_style = "space"    # 或 "tab"
indent_size = 4
line_ending = "lf"        # unix 风格

# 方法链断行策略
[format.chain]
break_on_long = true      # 长方法链自动断行

# 闭包格式化
[format.closure]
trailing_comma = true     # 多参数闭包末尾逗号

# 数组格式化
[format.array]
trailing_comma = true     # 多行数组末尾逗号

确定性格式化的价值:与 PHP-CS-Fixer 不同,Mago 的格式化是 AST → 输出的单向映射,不存在"配置 A 和配置 B 冲突导致不一致输出"的问题。格式化结果完全可预测,团队无需争论风格。

2.4 Guard(架构约束)

这是 Mago 最独特的能力——在 lint 层面强制执行架构规则

toml
# mago.toml — Guard 规则示例

# 禁止 Controller 直接访问数据库
[guard.rule.no_direct_db_in_controller]
description = "Controller 不应直接使用 Doctrine EntityManager"
pattern = "class *Controller"
disallow = "use Doctrine\\ORM\\EntityManager"

# 强制 Service 层只能通过 Repository 访问数据
[guard.rule.service_repo_only]
description = "Service 层必须通过 Repository 访问数据"
pattern = "class *Service"
disallow = "EntityManager::find"

# 禁止在 Model 中使用 HTTP 相关类
[guard.rule.no_http_in_model]
description = "Model 不应依赖 HTTP 上下文"
pattern = "class *Model"
disallow = "use Symfony\\HttpFoundation"

Guard 让你把架构决策从"口头约定"变成"自动化检查"——每次 lint 时自动验证,违反架构规则和违反代码风格一样报错。

三、从 PHPStan 迁移到 Mago 的实战指南

3.1 安装与初始化

bash
# 安装 Mago(无需 PHP 运行时)
curl --proto '=https' --tlsv1.2 -sSf https://carthage.software/mago.sh | bash

# 或者通过 Composer
composer require carthage-software/mago --dev

# 或者通过 Homebrew
brew install carthage-software/tap/mago

# 在项目根目录初始化(自动检测项目布局)
cd /your/project
mago init
# → 自动生成 mago.toml
# → 自动检测 PHP 版本、目录结构、命名空间约定

3.2 配置文件详解

toml
# mago.toml — 完整配置示例

[project]
php_version = "8.5"       # 目标 PHP 版本
source = "src"            # 源代码目录
tests = "tests"           # 测试目录

[analyze]
# 静态分析配置
strictness = "max"        # 最大严格度(类似 PHPStan level 8)
baseline = ".mago-baseline.json"  # baseline 文件路径

[analyze.plugins]
# 自定义类型提供器(类似 PHPStan extension)
larastan = true           # Laravel 类型推断
symfony = true            # Symfony 类型推断

[lint]
# Linter 配置
categories = ["correctness", "safety", "best_practices"]
auto_fix = true           # 保存时自动修复

[format]
# 格式化配置
print_width = 120
indent_style = "space"
indent_size = 4

[guard]
# 架构约束
rules = [
    "no_direct_db_in_controller",
    "service_repo_only",
    "no_http_in_model"
]

3.3 Baseline 策略:渐进式采用

大型 PHP 项目最怕的不是没有静态分析,而是开启分析后出现 1000+ 报错让人崩溃。Mago 的 Baseline 功能完美解决了这个问题:

bash
# 第一步:生成 baseline(记录当前所有问题)
mago analyze --generate-baseline > .mago-baseline.json

# 第二步:日常使用 baseline(只检测新问题)
mago analyze --baseline=.mago-baseline.json

# 第三步:逐步修复历史问题后更新 baseline
mago analyze --generate-baseline > .mago-baseline.json

实测数据:一个 3000 文件的 Laravel 项目:

首次运行(无 baseline):1,000+ 错误 → 心态崩溃
Baseline 后:0 新错误 → 心态正常
逐步修复:每周清理 50-100 个 baseline 条目
3 个月后:baseline 清零,全面严格模式

3.4 CI 集成

yaml
# GitHub Actions — Mago CI
name: Mago PHP Quality
on: [push, pull_request]

jobs:
  mago:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Mago
        run: curl --proto '=https' --tlsv1.2 -sSf https://carthage.software/mago.sh | bash

      - name: Static Analysis
        run: mago analyze --baseline=.mago-baseline.json

      - name: Lint Check
        run: mago lint --check  # --check 模式只报告不修改

      - name: Format Check
        run: mago format --check  # 确保格式一致性

3.5 编辑器集成

json
// VS Code settings.json — Mago LSP
{
    "mago.enable": true,
    "mago.phpVersion": "8.5",
    // 静态分析器还不稳定,建议先只用 formatter + linter
    "mago.noAnalyzer": false,
    // 保存时自动 lint + format
    "mago.fixOnSave": true,
    "mago.formatOnSave": true
}

四、Mago vs PHPStan vs Psalm:何时切换?

4.1 成熟度对比

维度Mago 1.0PHPStan 2.xPsalm
Formatter✅ 生产级❌ 无❌ 无
Linter✅ 生产级⚠️ 部分⚠️ 部分
静态分析⚠️ 假阳性较多✅ 生产级✅ 生产级
速度🚀 31x🐌 基准🐌 基准
框架扩展⚠️ Larastan/Symfony✅ 成熟生态✅ 成熟生态
闭源规则❌ 未来需 Rust✅ PHP 自定义✅ PHP 自定义

4.2 推荐策略

当前最佳实践(2026 年 7 月):
  ├─ Formatter:使用 Mago(确定性、快速、无需争论)
  ├─ Linter:使用 Mago(135 规则 + 自动修复)
  ├─ 静态分析:使用 PHPStan(成熟、假阳性少、生态丰富)
  ├─ 等待 Mago 2.0:静态分析器预计在 2.0 达到生产级
  └─ 长期目标:Mago 三合一统一工具链

不要急切换。Tempest 框架作者 Brent Roose 在 2026 年初确认 Mago 静态分析器"wasn't good enough yet: many false positives"。一个 3000 文件的项目测试发现 Mago v1.0.2 报告 1000+ 错误,而 PHPStan max level 报告 0 错误。

但这不影响 Mago 在 format + lint 层面的生产就绪性。Tempest 团队已经在生产环境运行 Mago formatter + linter 约 1 年。

五、Rust 重写工具链的深层逻辑

5.1 为什么 Rust 是工具链的未来

Rust 重写工具链浪潮(2024-2026):
  Python: uv(包管理)→ ruff(lint)→ Polars(数据)→ orjson(序列化)
  JavaScript: SWC(编译)→ Turbopack(打包)→ Bun(运行时)
  PHP: Mago(静态分析/lint/format)→ Mago(全工具链)
  
共同逻辑:
  ├─ 编译到原生二进制 → 无解释器 overhead
  ├─ 零成本抽象 → 性能接近 C/C++
  ├─ 内存安全 → 无 GC 暂停
  ├─ 单二进制 → 无运行时依赖
  └─ 并行计算 → 天然多线程

5.2 Mago 的内存策略

Mago 使用每线程内存池分配器

内存策略:
  ├─ 每个线程预分配大块内存(arena-like)
  ├─ 内部快速分配,无 malloc 系统调用
  ├─ 峰值内存比 PHP 工具略高(多线程 overhead)
  └─ 但开发时间节省远比几 GB 内存更有价值

这不是"内存浪费",而是用内存换时间的工程决策。在 CI 环境中,3 秒完成分析 vs 120 秒完成分析,差距是 2 分钟的 CI 等待时间 × 每天的推送次数 × 团队人数。

5.3 Mago 的 WASM Playground

Mago 提供了在线 Playground(mago.carthage.software/playground),通过 WebAssembly 在浏览器中运行完整的分析器:

bash
# 本地开发时也可以用 WASM 验证
# Mago 的 LSP 使用 WASM 编译的自定义规则
# 未来自定义 lint 规则需要用 Rust 编写并编译为 WASM

这意味着未来的 Mago 自定义规则不再用 PHP 编写,而是用 Rust 编写 → 编译为 WASM → 注入 Mago 运行时。这是一个范式转变:PHP 工具的质量门槛从"会写 PHP"变成了"会写 Rust"。

六、PHP 生态的 Rust 化趋势

6.1 PHPverse 2026 的信号

Larry Garfield(PHP 社区核心人物、Drupal 架构师)在 PHPverse 2026 上明确表示:

"FrankenPHP is the most important thing happening right now in PHP."

而 FrankenPHP 也是用 Rust/C 写的 PHP 运行时。Larry 选出的"过去十年最佳 PHP 特性"是构造器属性提升(constructor property promotion),但他认为"最重要的正在进行的事情"是 FrankenPHP 和 Rust 化。

6.2 PHP 工具链 Rust 化全景

PHP 工具链 Rust 化路线图:
  运行时层:FrankenPHP(Rust+C)→ 替代 mod_php/FPM
  分析层:  Mago(Rust)→ 替代 PHPStan/Psalm/PHP-CS-Fixer
  编译层:  TypePHP/Swoole AOT → PHP 静态编译为原生二进制
  引擎层:  Phargo(Rust 重写 PHP 引擎)→ 实验性
  
每一层都在被 Rust 重写或 Rust 化替代

七、实战案例:在 Laravel 项目中引入 Mago

7.1 完整迁移步骤

bash
# 1. 安装 Mago
composer require carthage-software/mago --dev

# 2. 初始化(自动检测 Laravel 项目结构)
mago init
# → 生成 mago.toml,自动配置 src/app 目录

# 3. 生成 baseline
mago analyze --generate-baseline > .mago-baseline.json

# 4. 添加 Guard 规则(强制 Laravel 架构)
# 编辑 mago.toml,添加:
toml
# Laravel 架构 Guard 规则
[guard.rule.controller_no_model_direct]
description = "Controller 不应直接调用 Model::find(),应通过 Service"
pattern = "class *Controller"
disallow = "App\\Models\\*::find"

[guard.rule.service_layer_only]
description = "Service 层不应依赖 HTTP Request"
pattern = "class *Service"
disallow = "Illuminate\\Http\\Request"

[guard.rule.no_db_in_view]
description = "Blade 视图不应包含数据库查询"
pattern = "*.blade.php"
disallow = "DB::table|Eloquent::"
bash
# 5. 设置 pre-commit hook
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/sh
mago format --check
mago lint --check
mago analyze --baseline=.mago-baseline.json
EOF
chmod +x .git/hooks/pre-commit

# 6. CI 集成(GitHub Actions)
# 见上文 CI 配置

7.2 性能实测

项目:500 文件 Laravel 应用,约 50K LOC

Mago 全流程(analyze + lint + format):
  首次运行:4.2s
  增量运行(单文件修改):0.3s

PHPStan level 8:
  首次运行:78s
  增量运行:15s

日常开发体验对比:
  Mago: 保存 → 0.3s 反馈 → 继续编码
  PHPStan: 保存 → 15s 反馈 → 已经忘了刚才改了什么

八、未来展望与注意事项

8.1 Mago 2.0 路线图

  • LSP 稳定化:当前 LSP 是 unstable preview,协议和 CLI flag 可能无通知变更
  • 静态分析器成熟:减少假阳性,达到 PHPStan max level 的准确度
  • 自定义规则:Rust 编写 → WASM 编译 → 注入 Mago
  • PHPDoc 格式化:当前不支持 PHPDoc block 格式化(对 Drupal 项目是 blocker)
  • Composer 包生态:类似 Larastan 的框架扩展包

8.2 注意事项

  1. Analyzer 假阳性:在 3000 文件项目上 Mago 报 1000+ 错误而 PHPStan 报 0。目前只用 format + lint,不要用 analyzer 替代 PHPStan
  2. 无 PHPStan 扩展生态:依赖 Larastan、Symfony PHPStan Extension 的项目会看到大量假阳性
  3. 自定义规则门槛:未来自定义规则需要 Rust(编译为 WASM),不是 PHP
  4. Doc 格式化缺失:不支持 PHPDoc block 格式化,对严格编码标准项目是 blocker

九、参考资料


Mago 1.0.0 是 PHP 工具链 Rust 化浪潮的第一座里程碑。在 format + lint 层面它已经是生产级工具,31 倍的速度提升让"每次保存即分析"从理想变成现实。但静态分析器还不成熟,自定义规则将需要 Rust 而非 PHP——这既是速度的代价,也是范式转变的开始。对于 PHP 开发者,当前的最佳策略是:Mago 做 format + lint,PHPStan 做静态分析,等待 Mago 2.0 完成三合一统一。

上次更新于: