前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Phar:PHP应用程序代码打包工具解决方案

Phar:PHP应用程序代码打包工具解决方案

作者头像
Tinywan
发布2024-04-15 10:50:49
1010
发布2024-04-15 10:50:49
举报
文章被收录于专栏:开源技术小栈开源技术小栈

简介

对于Web应用的开发,如果你没用使用正确的工具,那开发过程可能会变得困难和痛苦。如果你之前开发过Java程序,我相信你肯定知道Jar文件(Jar是Java ARchive的缩写)。一个应用,包括所有的可执行、可访问的文件,都打包进了一个JAR文件里,使得部署过程十分简单。

Phar全称为PHP Archive,是一种PHP的压缩归档格式,用于将一个或多个PHP文件以及它们的依赖文件打包成一个单独的文件。是PHP里类似于JAR的一种打包文件。如果你使用的是 PHP 5.3 或更高版本,那么Phar后缀文件是默认开启支持的,你不需要任何其他的安装就可以使用它

Phar扩展提供了一种将整个 PHP 应用程序放入单个叫做phar(PHP 归档)文件的方法,以便于分发和安装。除了提供此服务外,phar 扩展还提供了一种文件格式抽象方法,用于通过 PharData 类创建和操作 tar 和 zip 文件,就像 PDO 提供访问不同数据库的统一接口一样。与不能在不同数据库之间转换的 PDO 不同,phar 还可以使用一行代码在 tar、zip 和 phar 文件格式之间进行转换。

配置

PHAR文件缺省状态是只读的,使用Phar文件不需要任何的配置。部署非常方便。因为我们现在需要创建一个自己的Phar文件,所以需要允许写入Phar文件,这需要修改一下 php.ini

打开 php.ini,找到 phar.readonly 指令行,修改成:

代码语言:javascript
复制
phar.readonly = 0

现在,我们就可以来把PHP应用打包成Phar文件了。

第一个 PHAR 文件

首先我要按按照一个的规则创建应用的目录结构,就行下面这样:

其中的build目录里将放置 PHAR 文件,这样能避免它跟源码程序混合到一起。src放的就是我们的PHP源码。

index.php会成为我们的应用的入口程序,common.php可以放置应用需要的一些共有代码,config.ini是我们的配置文件。

index.php大概是这样样子:

代码语言:javascript
复制
<?php
require_once "phar://myapp.phar/common.php";
$config = parse_ini_file("config.ini");
AppManager::run($config);

common.php 大概是这样的:

代码语言:javascript
复制
<?php
class AppManager
{
    public static function run($config) {
         echo "Application is now running with the following configuration... ";
         var_dump($config);
     }
}

而 `config.ini 的内容是这样的:

代码语言:javascript
复制
[database]
host=localhost
db=dbname
user=myuser
pass=dbpass

创建 PHAR 文件

在我们的PHP应用目录里,需要有一个创建Phar文件的脚本,我们给它起名叫create-phar.php,放置到myapp的跟目录下,里面添加如下代码:

代码语言:javascript
复制
<?php
$srcRoot = "~/myapp/src";
$buildRoot = "~/myapp/build";
 
$phar = new Phar($buildRoot . "/myapp.phar", 
  FilesystemIterator::CURRENT_AS_FILEINFO |       FilesystemIterator::KEY_AS_FILENAME, "myapp.phar");
$phar["index.php"] = file_get_contents($srcRoot . "/index.php");
$phar["common.php"] = file_get_contents($srcRoot . "/common.php");
$phar->setStub($phar->createDefaultStub("index.php"));

copy($srcRoot . "/config.ini", $buildRoot . "/config.ini");

打开命令行窗口,切换到 myapp 目录下,运行命令:

代码语言:javascript
复制
aabouzekry@platinum:~/myapp$ php create-phar.php

运行了上面的命令后,你会在build目录里发现一个myapp.phar文件,还有一个config.ini的副本。将这两个文件拷贝到WEB服务器的服务根目录里(e.g.htdocs)。

我们可以直接访问Phar打包的应用,但这需要额外配置web server来将Phar文件发送给正确PHP解析器。另外一个办法是创建一个run脚本,include 这个Phar文件。

在web server的根目录创建一个叫run.php的PHP脚本:

代码语言:javascript
复制
<?php
require "myapp.phar";

这段代码的作用就是可以让你免去了去配置web server来直接解析Phar文件。如果你的应用使用的是一个共享的虚拟主机,没有权限来配置web server,那么,这种方式是一个完美的解决方案。

创建了run.php后,我们的web server的根目录会变成这样:

打开浏览器,将地址指向 run.php,你能看到下面的输出:

Phar的运行原理

让我们再重新看一下 create-phar.php 中的代码,了解每段代码的作用。先看看这几行:

代码语言:javascript
复制
<?php
$phar = new Phar($buildRoot . "/myapp.phar", 
        FilesystemIterator::CURRENT_AS_FILEINFO |
        FilesystemIterator::KEY_AS_FILENAME, "myapp.phar");

一个新Phar对象的创建通常需要三个参数。第一个参数是Phar文件的路径。你不仅可以通过它创建Phar文件,还可以对现存的Phar文件进行操作。

第二个参数是设定Phar对象如何处理文件。Phar对象继承了 PHPRecursiveDirectoryIterator对象,这个参数是直接传递到父类里。这里提供的值是RecursiveDirectoryIterator的缺省值,能满足目前的要求。

第三个参数是Phar文件的别名,在内部引用这个Phar文件时都要使用这个别名。也就是说,Phar内部文件的相互include都需要显式的使用这个别名。例如,之前的index.phpcommon.php的引用就是这种方式。

代码语言:javascript
复制
<?php
require_once "phar://myapp.phar/common.php";

在Phar对象创建之后, index.phpcommon.php 就被加入了Phar文件里了。Phar 对象是一个数组,file_get_contents() 方法将各个文件的内容读到数组里。你可以向里面添加很多的文件,但如果你考虑添加大量的文件,比如说整个目录下的文件,你可以考虑使用更方便的 buildFromDirectory() 方法。

代码语言:javascript
复制
<?php
$phar->buildFromDirectory("/path/to/dir",'/.php$/');

buildFromDirectory()的第一个参数是目录的路径;第二个参数是可选的,是用正则表达式过滤文件的类型。如果目录下的所有文件都要include,这个参数可以忽略。

setStub()用来创建stub文件,stub文件用来告诉Phar在被加载时干什么。

最后,config.inisrc被拷贝到build目录下。

Stub文件

运行Phar文件时,stub文件被当做一个meta文件来初始化Phar, 并告诉Phar文件在被调用时该做什么。在我们的例子中,使用的是 createDefaultStub() 方法,生成的缺省stub文件包含如下的代码:

代码语言:javascript
复制
<?php
Phar::mapPhar();
include "phar://myapp.phar/index.php";
__HALT_COMPILER();

createDefaultStub()方法缺省创建的stub文件的内容很简单。Phar::mapPhar()用来分析Phar文件的元数据,并初始化它。stub文件的结尾处需要调用__HALT_COMPILER()方法,这个方法后不能留空格。__HALT_COMPILER()会立即终止PHP的运行,防止include的文件在此方法后仍然执行。这是Phar必须的,没有它Phar将不能正常运行。

除此之外,我们还可以创建自己的stub文件来执行自定义的初始化过程,像这样加载自定义文件:

代码语言:javascript
复制
<?php
$phar->setStub(file_get_contents("stub.php"));

Phar文件的一些缺陷

如果你开发的类库或可引用程序需要被多个项目使用,把它打包成Phar文件是一个省事的解决方案。Phar文件是经过高度优化过的,它和普通文件的执行效率相比完全不弱,所以,你不需要担心效率问题。

但需要注意的是,Phar文件的使用有一些限制。下面是一些提示让你更好的理解它:

  • 我们可以整个应用都打包到一个Phar文件里,但Phar只提供了一个单一入口。
  • 在生产环境里,我们应该避免将东西回写进Phar,我们应该将哪些可能被修改的文件放到Phar之外,在标准PHP安装里,Phar是不允许回写的,因为安全问题。

总结

Phar能帮我们在打包和部署PHP应用上免去大量的麻烦,我推荐大家试试它。这篇文章只是介绍了Phar的一些主要概念,包括如何创建Phar,include文件,介绍stub文件的作用,如何访问Phar里的文件。

本文参与?腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2024-04-04,如有侵权请联系?cloudcommunity@tencent.com 删除

本文分享自 开源技术小栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • 配置
  • 第一个 PHAR 文件
  • 创建 PHAR 文件
  • Phar的运行原理
  • Stub文件
  • Phar文件的一些缺陷
  • 总结
相关产品与服务
轻量应用服务器
轻量应用服务器(TencentCloud Lighthouse)是新一代开箱即用、面向轻量应用场景的云服务器产品,助力中小企业和开发者便捷高效的在云端构建网站、Web应用、小程序/小游戏、游戏服、电商应用、云盘/图床和开发测试环境,相比普通云服务器更加简单易用且更贴近应用,以套餐形式整体售卖云资源并提供高带宽流量包,将热门开源软件打包实现一键构建应用,提供极简上云体验。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com