mise 升级又出幺蛾子

使用 mise 管理 Windows 平台的开发工具已经有一阵子了。这几天突然发现 mise 管理的 PHP 失效了。现象是找不到 php 命令、重新安装 PHP 失败。疑为某次 mise 版本升级导致的问题。

mise doctor 命令进行诊断:

version: 2026.7.15 windows-x64 (2026-07-27)
shims_on_path: no
self_update_available: yes

... ...

plugins:
  php     https://github.com/jdx/vfox-php.git#b423527
  ... ...

path:
  C:\mise\installs\php\8.5.5\bin
  ... ...

PHP 失效的问题找到了:PATH 的原本路径应该是 C:\\mise\\installs\\php\\8.5.5,但现在变成了 C:\\mise\\installs\\php\\8.5.5\\bin,路径末尾多出了 bin——这显然是 Linux 风格的路径。

而使用 mise install php 8.5.5 命令安装 PHP 出现如下错误:

mise Downloading https://github.com/php/php-src/archive/php-8.5.5.tar.gz
mise Verifying "C:\\mise\\downloads\\php\\8.5.5\\php-8.5.5\\php-8.5.5.tar.gz" checksum
mise Extracting "C:\\mise\\downloads\\php\\8.5.5\\php-8.5.5\\php-8.5.5.tar.gz" to "C:\\mise\\installs\\php\\8.5.5"
[email protected]      install
The system cannot find the path specified.
mise [php] Running buildconf...
[email protected]      install
mise ERROR Failed to install vfox:[email protected]: runtime error: C:\mise\plugins\php\hooks/post_install.lua:79: Failed to run buildconf
stack traceback:
        [C]: in function 'error'
        C:\mise\plugins\php\hooks/post_install.lua:79: in function 'PLUGIN.PostInstall'
        crates\vfox\src\plugin.rs:189:2: in main chunk
mise ERROR Version: 2026.7.15 windows-x64 (2026-07-27)
mise ERROR Run with --verbose or MISE_VERBOSE=1 for more information

安装脚本尝试通过源代码编译 PHP,而不是直接下载 Windows 二进制包。

根据以上结果推测,问题应该出在 mise 的 PHP 插件上。查看当前的版本的 mise 源代码

tomlbackends = ["vfox:jdx/vfox-php", "asdf:mise-plugins/asdf-php"]
description = "popular general-purpose scripting language that is especially suited to web development. Fast, flexible and pragmatic, PHP powers everything from your blog to the most popular websites in the world"
registry/php.toml

与上个月的版本进行比较:

tomlbackends = ["asdf:mise-plugins/asdf-php", "vfox:mise-plugins/vfox-php"]
description = "popular general-purpose scripting language that is especially suited to web development. Fast, flexible and pragmatic, PHP powers everything from your blog to the most popular websites in the world"
registry/php.toml

插件的 banckend 变更了。问题应该就出在这里——我记以前 vfox 的插件都使用的是 vfox 官方的源,也就是 version-fox/vfox-php 。现在 mise 项目自己 fork 了这些插件。

来比较一下原版 vfox-php 和 mise 版本 vfox-php 有什么差异。首先看原版:

lua--- Each SDK may have different environment variable configurations.
--- This allows plugins to define custom environment variables (including PATH settings)
--- Note: Be sure to distinguish between environment variable settings for different platforms!
--- @param ctx table Context information
--- @field ctx.path string SDK installation directory
function PLUGIN:EnvKeys(ctx)
    --- this variable is same as ctx.sdkInfo['plugin-name'].path
    local mainPath = ctx.path
    local bin = ""
    if RUNTIME.osType ~= "windows" then
        bin = "/bin"
    end

    return {
        {
            key = "PATH",
            value = mainPath .. bin
        }
    }
end
hooks/env_keys.lua

如果操作系统不是 Windows,PATH 路径加 /bin ——完全没毛病。

lualocal http = require('http')
local html = require('html')
local util = require('util')
require('constants')

--- Return all available versions provided by this plugin
--- @param ctx table Empty table used as context, for future extension
--- @return table Descriptions of available versions and accompanying tool descriptions
function PLUGIN:Available(ctx)
    if RUNTIME.osType == 'windows' then
        return GetReleaseListForWindows()
    else
        return GetReleaseListForLinux()
    end
end
hooks/available.lua

如果操作系统是 Windows,调用 GetReleaseListForWindows() ——非常好。

再来看看 mise 自己维护的 vfox-php 代码:

lua--- Returns environment variables for PHP
--- @param ctx table Context provided by vfox
--- @return table Environment configuration
function PLUGIN:EnvKeys(ctx)
    local sdkInfo = ctx.sdkInfo["php"]
    local installDir = sdkInfo.path

    local envs = {
        {
            key = "PATH",
            value = installDir .. "/bin",
        },
        {
            key = "PATH",
            value = installDir .. "/sbin",
        },
        {
            key = "PATH",
            value = installDir .. "/.composer/vendor/bin",
        },
        {
            key = "COMPOSER_HOME",
            value = installDir .. "/.composer",
        },
    }

    -- Add LD_LIBRARY_PATH on Linux
    if RUNTIME.osType == "linux" then
        table.insert(envs, {
            key = "LD_LIBRARY_PATH",
            value = installDir .. "/lib",
        })
    end

    return envs
end
hooks/env_keys.lua
lua--- Returns available PHP versions from GitHub php-src tags
--- @param ctx table Context provided by vfox
--- @return table Available versions
function PLUGIN:Available(ctx)
    local http = require("http")
    local result = {}
    local seen = {}

    -- Fetch tags from php-src GitHub repository
    -- We use the GitHub API to get all tags
    local page = 1
    local per_page = 100

    while true do
        local resp, err = http.get({
            url = "https://api.github.com/repos/php/php-src/tags?per_page=" .. per_page .. "&page=" .. page,
            headers = {
                ["Accept"] = "application/vnd.github.v3+json",
                ["User-Agent"] = "vfox-php",
            },
        })

        if err ~= nil or resp.status_code ~= 200 then
            -- Fallback: try git ls-remote approach via web
            break
        end

        local json = require("json")
        local tags = json.decode(resp.body)

        if tags == nil or #tags == 0 then
            break
        end

        for _, tag in ipairs(tags) do
            local name = tag.name
            -- Match tags like "php-8.4.17", "php-8.3.0RC1", etc.
            local version = string.match(name, "^php%-([0-9]+%.[0-9]+%.%d+[%w%-]*)$")
            if version ~= nil and not seen[version] then
                seen[version] = true
                table.insert(result, { version = version })
            end
        end

        page = page + 1

        -- Stop if we got less than a full page
        if #tags < per_page then
            break
        end

        -- Safety limit
        if page > 20 then
            break
        end
    end

    -- Sort versions (newest first)
    table.sort(result, function(a, b)
        return compare_versions(a.version, b.version) > 0
    end)

    return result
end
hooks/available.lua

都什么鬼!压根就没判断操作系统——路径全部加 /bin、安装都从源代码编译——也不知道维护者脑子里装的啥。

解决方法就是删除 mise 官方的 PHP 插件,安装 version-fox/vfox-php 插件:

shellmise plugins remove php
mise plugins install php https://github.com/version-fox/vfox-php.git