PHP开发之归档格式phar文件概念与用法详解【创建,使用,解包还原提取】


Posted in PHP onNovember 17, 2017

本文实例讲述了PHP开发之归档格式phar文件概念与用法。分享给大家供大家参考,具体如下:

一个php应用程序往往是由多个文件构成的,如果能把他们集中为一个文件来分发和运行是很方便的,这样的列子有很多,比如在window操作系统上面的安装程序、一个jquery库等等,为了做到这点php采用了phar文档文件格式,这个概念源自java的jar,但是在设计时主要针对 PHP 的 Web 环境,与 JAR 归档不同的是Phar 归档可由 PHP 本身处理,因此不需要使用额外的工具来创建或使用,使用php脚本就能创建或提取它。phar是一个合成词,由PHP 和 Archive构成,可以看出它是php归档文件的意思。

关于phar的官网文档请见http://php.net/manual/zh/book.phar.php,本文档可以看做和官网文档互为补充

phar归档文件有三种格式:tar归档、zip归档、phar归档,前两种执行需要php安装Phar 扩展支持,用的也比较少,这里主要讲phar归档格式。

phar格式归档文件可以直接执行,它的产生依赖于Phar扩展,由自己编写的php脚本产生。

Phar 扩展对 PHP 来说并不是一个新鲜的概念,在php5.3已经内建于php中,它最初使用 PHP 编写并被命名为 PHP_Archive,然后在 2005 年被添加到 PEAR 库。由于在实际中,解决这一问题的纯 PHP 解决方案非常缓慢,因此 2007 年重新编写为纯 C 语言扩展,同时添加了使用 SPL 的 ArrayAccess 对象遍历 Phar 归档的支持。自那时起,人们做了大量工作来改善 Phar 归档的性能。

Phar 扩展依赖于php流包装器,关于此可参考前面一篇文章PHP流Streams、包装器wrapper概念与用法实例详解

很多php应用都是以phar格式分发并运行的,著名的有依赖管理:composer、单元测试:phpunit,下面我们来看一看如何创建、运行、提取还原。

phar文件的创建:

首先在php.ini中修改phar.readonly这个选项,去掉前面的分号,并改值为off,由于安全原因该选项默认是on,如果在php.ini中是禁用的(值为0或off),那么在用户脚本中可以开启或关闭,如果在php.ini中是开启的,那么用户脚本是无法关闭的,所以这里设置为off来展示示例。

我们来建立一个项目,在服务器根目录中建立项目文件夹为project,目录内的结构如下:

file
  -yunek.js
  -yunke.css
lib
  -lib_a.php
template
  -msg.html
index.php
Lib.php

其中file文件夹有两个内容为空的js和css文件,仅仅演示phar可以包含多种文件格式

lib_a.php内容如下:

<?php
/**
 * Created by yunke.
 * User: yunke
 * Date: 2017/2/10
 * Time: 9:23
 */
function show(){
  echo "l am show()";
}

msg.html内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>phar</title>
</head>
<body>
<?=$str; ?>
</body>
</html>

index.php内容如下:

<?php
/**
 * Created by yunke.
 * User: yunke
 * Date: 2017/2/10
 * Time: 9:17
 */
require "lib/lib_a.php";
show();
$str = isset($_GET["str"]) ? $_GET["str"] : "hello world";
include "template/msg.html";

Lib.php内容如下:

<?php
/**
 * Created by yunke.
 * User: yunke
 * Date: 2017/2/10
 * Time: 9:20
 */
function yunke()
{
  echo "l am yunke()";
}

项目文件准备好了,开始创建,现在在project文件夹同级目录建立一个yunkeBuild.php,用于产生phar格式文件,内容如下:

<?php
/**
 * Created by yunke.
 * User: yunke
 * Date: 2017/2/10
 * Time: 9:36
 */
//产生一个yunke.phar文件
$phar = new Phar('yunke.phar', 0, 'yunke.phar');
// 添加project里面的所有文件到yunke.phar归档文件
$phar->buildFromDirectory(dirname(__FILE__) . '/project');
//设置执行时的入口文件,第一个用于命令行,第二个用于浏览器访问,这里都设置为index.php
$phar->setDefaultStub('index.php', 'index.php');

然后在浏览器中访问这个yunkeBuild.php文件,将产生一个yunke.phar文件,此时服务器根目录结构如下:

project
yunkeBuild.php
yunke.phar

这就是产生一个phar归档文件最简单的过程了,更多内容请看官网,这里需要注意的是如果项目不具备单一执行入口则不宜使用phar归档文件

phar归档文件的使用:

我们在服务器根目录建立一个index.php文件来演示如何使用上面创建的phar文件,内容如下:

<?php
/**
 * Created by yunke.
 * User: yunke
 * Date: 2017/2/8
 * Time: 9:33
 */
require "yunke.phar";
require "phar://yunke.phar/Lib.php";
yunke();

如果index.php文件中只有第一行,那么和不使用归档文件时,添加如下代码完全相同:

require "project/index.php";

如果没有第二行,那么第三行的yunke()将提示未定义,所以可见require一个phar文件时并不是导入了里面所有的文件,而只是导入了入口执行文件而已,但在实际项目中往往在这个入口文件里导入其他需要使用的文件,在本例中入口执行文件为project/index.php

phar文件的提取还原:

我们有时候会好奇phar里面包含的文件源码,这个时候就需要将phar文件还原,如果只是看一看的话可以使用一些ide工具,比如phpstorm 10就能直接打开它,如果需要修改那么就需要提取操作了,为了演示,我们下载一个composer.phar放在服务器目录,在根目录建立一个get.php文件,内容如下:

<?php
/**
 * Created by yunke.
 * User: yunke
 * Date: 2017/2/9
 * Time: 19:02
 */
$phar = new Phar('composer.phar');
$phar->extractTo('composer'); //提取一份原项目文件
$phar->convertToData(Phar::ZIP); //另外再提取一份,和上行二选一即可

用浏览器访问这个文件,即可提取出来,以上列子展示了两种提取方式:第二行将建立一个composer目录,并将提取出来的内容放入,第三行将产生一个composer.zip文件,解压即可得到提取还原的项目文件。

补充:

1、在部署phar文件到生产服务器时需要调整服务器的配置,避免当访问时浏览器直接下载phar文件

2、可以为归档设置别名,别名保存在归档文件中永久保存,它可以用一个简短的名字引用归档,而不管归档文件在文件系统中存储在那里,设置别名:

$phar = new Phar('lib/yunke.phar', 0);
$phar->setAlias ( "yun.phar");

设置别名后可以如下使用:

<?php
require "lib/yunke.phar";
require "phar://yun.phar/Lib.php"; //使用别名访问归档文件
require "phar://lib/yunke.phar/Lib.php"; //当然仍然可以使用这样的方式去引用

如果在制作phar文件时没有指定别名,也可以在存根文件里面使用Phar::mapPhar('yunke.phar');指定

3、归档文件中有一个存根文件,其实就是一段php执行代码,在制作归档时可以设置,直接执行归档文件时,其实就是执行它,所以它是启动文件;在脚本中包含归档文件时就像包含普通php文件一样包含它并运行,但直接以phar://的方式包含归档中某一个文件时不会执行存根代码, 往往在存根文件里面require包含要运行的其他文件,对存根文件的限制仅为以__HALT_COMPILER();结束,默认的存根设计是为在没有phar扩展时能够运行,它提取phar文件内容到一个临时目录再执行,不过从php5.3开始该扩展默认内置启用了

4、制作的phar文件不能被改动,因此配置文件之类的文件需要另外放置在归档文件外面

5、mapPhar函数:这个函数只应该在stub存根代码中调用,在没有设置归档别名的时候可以用来设置别名,打开一个引用映射到phar流

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
PHP常用特殊运算符号和函数总结(php新手入门必看)
Feb 02 PHP
php缩放图片(根据宽高的等比例缩放)实例介绍
Jun 09 PHP
PHP、Nginx、Apache中禁止网页被iframe引用的方法
Oct 01 PHP
php使用gettimeofday函数返回当前时间并存放在关联数组里
Mar 19 PHP
php微信开发之批量生成带参数的二维码
Jun 26 PHP
php版微信公众平台接口参数调试实现判断用户行为的方法
Sep 23 PHP
php中输出json对象的值(实现方法)
Mar 07 PHP
php处理多图上传压缩代码功能
Jun 13 PHP
详解php协程知识点
Sep 21 PHP
PHP session垃圾回收机制实例分析
Jun 28 PHP
PHP实现15位身份证号转18位的方法分析
Oct 16 PHP
TP5框架页面跳转样式操作示例
Apr 05 PHP
PHP流Streams、包装器wrapper概念与用法实例详解
Nov 17 #PHP
PHP实现求两个字符串最长公共子串的方法示例
Nov 17 #PHP
PHP实现求解最长公共子串问题的方法
Nov 17 #PHP
php大小写转换函数(strtolower、strtoupper)用法介绍
Nov 17 #PHP
PHP 实现人民币小写转换成大写的方法及大小写转换函数
Nov 17 #PHP
关于php支持的协议与封装协议总结(推荐)
Nov 17 #PHP
PHP实现绘制二叉树图形显示功能详解【包括二叉搜索树、平衡树及红黑树】
Nov 16 #PHP
You might like
php mysql索引问题
2008/06/07 PHP
php中模拟POST传递数据的两种方法分享
2011/09/16 PHP
PHP实现微信红包金额拆分试玩的算法示例
2018/04/07 PHP
PHP观察者模式示例【Laravel框架中有用到】
2018/06/15 PHP
PHP+MySQL实现在线测试答题实例
2020/01/02 PHP
jQuery语法总结和注意事项小结
2012/11/11 Javascript
原生JS实现加入收藏夹的代码
2013/10/24 Javascript
Javascript 拖拽的一些简单的应用(逐行分析代码,让你轻松了拖拽的原理)
2015/01/23 Javascript
JavaScipt选取文档元素的方法(推荐)
2016/08/05 Javascript
AngularJs bootstrap搭载前台框架——基础页面
2016/09/01 Javascript
js数字舍入误差以及解决方法(必看篇)
2017/02/28 Javascript
详解jquery选择器的原理
2017/08/01 jQuery
使用3D引擎threeJS实现星空粒子移动效果
2020/09/13 Javascript
npm全局模块卸载及默认安装目录修改方法
2018/05/15 Javascript
微信小程序开发之路由切换页面重定向问题
2018/09/18 Javascript
微信小程序自定义组件的实现方法及自定义组件与页面间的数据传递问题
2018/10/09 Javascript
JS回调函数原理与用法详解【附PHP回调函数】
2019/07/20 Javascript
基于Vue和Element-Ui搭建项目的方法
2019/09/06 Javascript
ES6 proxy和reflect的使用方法与应用实例分析
2020/02/15 Javascript
vue css 引入asstes中的图片无法显示的四种解决方法
2020/03/16 Javascript
[02:43]DOTA2英雄基础教程 圣堂刺客
2013/12/09 DOTA
python os.path模块常用方法实例详解
2018/09/16 Python
用Django写天气预报查询网站
2018/10/21 Python
Python3对称加密算法AES、DES3实例详解
2018/12/06 Python
python重试装饰器的简单实现方法
2019/01/31 Python
Flask模板引擎之Jinja2语法介绍
2019/06/26 Python
使用Python实现Wake On Lan远程开机功能
2020/01/22 Python
Python3 集合set入门基础
2020/02/10 Python
Keras 实现加载预训练模型并冻结网络的层
2020/06/15 Python
用HTML5中的Canvas结合公式绘制粒子运动的教程
2015/05/08 HTML / CSS
详解HTML5之pushstate、popstate操作history,无刷新改变当前url
2017/03/15 HTML / CSS
CK澳大利亚官网:Calvin Klein澳大利亚
2020/12/12 全球购物
公司财务自我评价分享
2013/12/17 职场文书
股权转让意向书
2014/04/01 职场文书
超市优秀员工获奖感言
2014/08/15 职场文书
12.4法制宣传日活动总结
2014/08/26 职场文书