PHP无法真正编译为EXE,所谓打包实为将解释器、脚本及依赖库封装成自解压容器;主流方案是ExeOutput for PHP(商业、Windows)和PHP Desktop(开源、跨平台),需手动处理扩展依赖、路径适配与运行时限制。

PHP 本身不能直接编译成 EXE
PHP 是解释型语言,运行依赖 php.exe(或 php-cgi.exe)和扩展库,没有官方“编译为 Windows 可执行文件”的能力。所谓“PHP 打包成 EXE”,本质是把 PHP 解释器、你的脚本、依赖的 .dll 和启动逻辑打包进一个自解压/自运行容器,不是真正意义上的编译。
常用工具:ExeOutput for PHP 或 PHP Desktop
目前较稳定、仍在维护的方案只有两个:
-
ExeOutput for PHP(商业软件,Windows-only,界面化操作):它内置精简版 PHP(含常见扩展),把你的
.php文件和资源打包进单个.exe,运行时自动解压到临时目录并调用内嵌php-cgi.exe启动内置服务器; -
PHP Desktop(开源,跨平台,需手动配置):基于 Chromium + Python + PHP 构建桌面应用,需你自行编译或下载预编译版本,然后把项目放入
www/目录,修改phpdesktop-chrome\settings.json指向入口index.php。
注意:BoxedApp Packer、PPM 等老工具已多年未更新,对 PHP 8+ 支持极差,容易触发杀毒软件误报或启动失败。
关键依赖必须显式包含
即使使用 ExeOutput,也不能默认带上所有扩展。以下几类必须手动勾选或验证:
立即学习“PHP免费学习笔记(深入)”;
- 如果你用了
mysqli或pdo_mysql,得确保libmysql.dll(或php_mysqli.dll)被包含,并且 MySQL 客户端库版本与 PHP 编译时匹配; - 启用
openssl需确认ssleay32.dll和libeay32.dll(PHP 7.4 及以前)或libssl-1_1.dll/libcrypto-1_1.dll(PHP 8.0+)一并打包; - 读写 SQLite 数据库要包含
php_pdo_sqlite.dll和php_sqlite3.dll; - 使用
curl时,若提示Unable to load dynamic library 'php_curl.dll',大概率是缺少libcurl.dll或其依赖的libssh2.dll、nghttp2.dll。
建议在打包前,用命令行运行一次:
php -m | findstr -i "mysqli curl openssl sqlite"确认扩展已加载,再对照工具的扩展列表做勾选。
路径、权限与运行时行为差异
打包后的 EXE 运行环境和原始 PHP CLI 截然不同:
-
__DIR__和getcwd()指向的是临时解压目录(如C:\Users\XXX\AppData\Local\Temp\XXXXXX\),不是 EXE 所在目录 —— 必须用dirname($_SERVER['SCRIPT_FILENAME'])或realpath(getenv('APPDATA') . '/YourApp/')存放用户数据; - 无法使用
exec()、shell_exec()调用外部程序(除非你把对应.exe也打进包里,并用绝对路径调用); - Apache/Nginx 的重写规则(
.htaccess)完全无效,路由必须由 PHP 自己处理(如判断$_SERVER['REQUEST_URI']); - 某些杀软会拦截 EXE 启动子进程(尤其是带内置 Web 服务的),首次运行可能弹窗警告,需引导用户加白名单。
最常被忽略的一点:调试困难。EXE 内部错误不会直接输出,得在设置中开启日志(如 ExeOutput 的 Log errors to file),或改用 error_log() 写入指定路径排查。











