本文目录导读:

在PHP中使用Phar打包应用程序是一个很好的方式,可以创建自包含的可执行PHP文件,以下是详细的使用方法:
基本设置和创建
创建Phar文件的配置
<?php
// create_phar.php
// 确保Phar模块已启用
if (!extension_loaded('phar')) {
die('Phar扩展未启用');
}
// 关闭phar.readonly(在命令行下)
// 注意:需要在php.ini中设置 phar.readonly = 0
// 或者在命令行使用 -d phar.readonly=0
try {
// 设置phar文件的路径
$pharFile = 'myapp.phar';
// 如果文件已存在,先删除
if (file_exists($pharFile)) {
unlink($pharFile);
}
// 创建一个新的phar文件
$phar = new Phar($pharFile);
// 开始缓冲写入
$phar->startBuffering();
// 设置默认的启动文件(stub)
$defaultStub = $phar->createDefaultStub('index.php', 'cli.php');
// 将一个目录添加到phar中
// 第二个参数是phar内的相对路径
$phar->buildFromDirectory(__DIR__ . '/app');
// 添加单个文件
$phar->addFile('config/config.php', 'config/config.php');
// 可以设置phar的元数据
$phar->setMetadata([
'version' => '1.0.0',
'author' => 'Your Name',
'created' => date('Y-m-d H:i:s')
]);
// 压缩文件
$phar->compressFiles(Phar::GZ);
// 设置自定义的stub(可选)
// $phar->setStub($defaultStub);
// 或者自定义stub
$customStub = "#!/usr/bin/env php\n<?php\nPhar::mapPhar('myapp.phar');\nrequire 'phar://myapp.phar/index.php';\n__HALT_COMPILER(); ?>";
$phar->setStub($customStub);
// 结束缓冲
$phar->stopBuffering();
echo "Phar文件创建成功: {$pharFile}\n";
} catch (Exception $e) {
echo "创建失败: " . $e->getMessage() . "\n";
}
示例项目结构
myapp/
├── create_phar.php
├── index.php # Web入口
├── cli.php # CLI入口
├── app/
│ ├── controllers/
│ ├── models/
│ └── views/
├── config/
│ └── config.php
└── vendor/ # 第三方库
使用Phar文件
在命令行中执行
# 执行phar文件
php myapp.phar
# 或者如果你是直接运行的
./myapp.phar
# 查看phar内容
php -r "echo file_get_contents('phar://myapp.phar/index.php');"
# 列出phar文件内容
php -r "
$phar = new Phar('myapp.phar');
foreach (new RecursiveIteratorIterator($phar) as $file) {
echo $file->getFileName() . PHP_EOL;
}
"
在PHP代码中使用
<?php
// 加载phar文件
require 'myapp.phar';
// 或者使用stream wrapper
$content = file_get_contents('phar://myapp.phar/index.php');
// 包含phar中的特定文件
include 'phar://myapp.phar/config/config.php';
高级用法
完整的打包脚本示例
<?php
// package.php
class PharBuilder {
private $pharFile;
private $sourceDir;
private $mainEntry;
public function __construct($pharFile, $sourceDir, $mainEntry = 'index.php') {
$this->pharFile = $pharFile;
$this->sourceDir = $sourceDir;
$this->mainEntry = $mainEntry;
}
public function build() {
// 检查当前是否在web环境中
if (!in_array('phar', stream_get_wrappers())) {
throw new Exception('Phar wrapper不可用');
}
// 检查是否允许写入
if (ini_get('phar.readonly') == '1') {
throw new Exception('请在php.ini中设置 phar.readonly = 0');
}
if (file_exists($this->pharFile)) {
unlink($this->pharFile);
}
$phar = new Phar($this->pharFile);
$phar->startBuffering();
// 添加所有文件
$phar->buildFromDirectory($this->sourceDir);
// 创建默认的stub为web和cli
$phar->setStub(
$phar->createDefaultStub('web/index.php', 'cli.php')
);
// 可选:压缩文件
if ($this->compress()) {
$phar->compressFiles(Phar::GZ);
}
// 签名设置
$phar->setSignatureAlgorithm(Phar::SHA256);
$phar->stopBuffering();
echo "Phar文件已创建: " . $this->pharFile . "\n";
echo "文件大小: " . filesize($this->pharFile) . " bytes\n";
}
private function compress() {
// 可以在这里添加压缩选项配置
return true;
}
}
// 使用示例
try {
$builder = new PharBuilder(
'myapp.phar',
__DIR__ . '/project',
'index.php'
);
$builder->build();
} catch (Exception $e) {
echo "错误: " . $e->getMessage() . "\n";
}
注意事项
php.ini配置
; 关闭只读限制(开发环境) phar.readonly = 0 ; 启用phar支持 phar.require_hash = On ; 压缩支持 phar.cache_list =
性能优化
<?php
// 在phar中优化加载性能
// 1. 使用 __HALT_COMPILER() 正确终止
$stub = "<?php\nPhar::mapPhar('optimized.phar');\ninclude 'phar://optimized.phar/index.php';\n__HALT_COMPILER(); ?>";
$phar->setStub($stub);
// 2. 压缩文件减小体积
$phar->compressFiles(Phar::GZ);
// 3. 使用opcache
// 在php.ini中设置:
// opcache.enable_cli=1
// opcache.validate_timestamps=0
// 4. 将常用文件放在phar的前部
$phar->addFile('bootstrap.php');
$phar->addFile('core/Application.php');
// 按使用频率排序
常见命令
# 创建phar文件
php create_phar.php
# 运行phar文件
php myapp.phar
# 查看phar内容
php -r "var_dump(new Phar('myapp.phar'));"
# 验证phar文件
php -r "
try {
$phar = new Phar('myapp.phar');
$phar->getSignature();
echo 'Phar文件有效';
} catch (Exception $e) {
echo 'Phar文件无效: ' . $e->getMessage();
}
"
# 列出所有文件
php -r "
$phar = new Phar('myapp.phar');
foreach ($phar as $file) {
echo $file->getPathname() . PHP_EOL;
}
"
实际应用示例
<?php
// 创建一个包含多个模块的完整应用程序phar
// 项目结构
$projectFiles = [
'config/database.php',
'app/core/Autoloader.php',
'app/controllers/UserController.php',
'app/models/User.php',
'app/views/user/list.php',
'vendor/autoload.php',
'vendor/composer/autoload_real.php'
];
$phar = new Phar('cms.phar');
$phar->startBuffering();
// 从目录添加
$phar->buildFromDirectory(__DIR__ . '/project');
// 设置自动加载处理
$autoloadStub = function() {
spl_autoload_register(function ($class) {
$prefix = 'App\\';
$base_dir = 'phar://cms.phar/src/';
if (strpos($class, $prefix) === 0) {
$class = substr($class, strlen($prefix));
$file = $base_dir . str_replace('\\', '/', $class) . '.php';
if (file_exists($file)) {
require $file;
}
}
});
};
// 创建引导文件
$bootstrap = '<?php' . PHP_EOL;
$bootstrap .= 'spl_autoload_register(function($class) {' . PHP_EOL;
$bootstrap .= ' $prefix = "App\\\\";' . PHP_EOL;
$bootstrap .= ' $base_dir = "phar://cms.phar/src/";' . PHP_EOL;
$bootstrap .= ' if (strpos($class, $prefix) === 0) {' . PHP_EOL;
$bootstrap .= ' $class = substr($class, strlen($prefix));' . PHP_EOL;
$bootstrap .= ' $file = $base_dir . str_replace("\\\\", "/", $class) . ".php";' . PHP_EOL;
$bootstrap .= ' if (file_exists($file)) require $file;' . PHP_EOL;
$bootstrap .= ' }' . PHP_EOL;
$bootstrap .= '});' . PHP_EOL;
$bootstrap .= 'require "phar://cms.phar/config/database.php";' . PHP_EOL;
$bootstrap .= '// 应用程序逻辑' . PHP_EOL;
$phar->addFromString('bootstrap.php', $bootstrap);
$phar->setStub(
"#!/usr/bin/env php\n<?php\nPhar::mapPhar('cms.phar');\nrequire 'phar://cms.phar/bootstrap.php';\n__HALT_COMPILER(); ?>"
);
$phar->stopBuffering();
echo "CMS Phar创建成功!\n";
这些示例应该能帮助你开始使用Phar打包PHP应用程序,记得在开发过程中经常测试,确保所有功能都能正常工作。