您的位置:首页 > 编程语言 > PHP开发

PHP V5.3 中的新特性,第 4 部分: 创建并使用 Phar 归档

2015-01-15 00:00 141 查看
摘要: PHP V5.3 将于不久后发布。“PHP V5.3 中的新特性” 系列文章将持续介绍该发行版提供的令人兴奋的新特性。本系列的 PHP V5.3 中的新特性,第 1 部分:对象接口的变化 介绍了 PHP 5.3 中对面向对象编程及对象处理所做的更改,PHP V5.3 中的新特性,第 2 部分:闭包及 lambda 函数 介绍了闭包函数及 lambda 函数。在 PHP V5.3 中的新特性,第 3 部分:名称空间 中,我们探讨了名称空间,这是该 PHP 版本中最令人期待也是最具争议的特性之一。本文是第 4 部分,我们将进一步研究 Phar,这是一种用于 PHP 的归档格式。它不仅可以用于...

Phar 归档的概念来自 Java™ 技术的 JAR 归档,它允许使用单个文件打包应用程序,这个文件中包含运行应用程序所需的所有东西。该文件不同于单个可执行文件,后者通常由编程语言生成,比如 C,因为该文件实际上是一个归档文件而非编译过的应用程序。因此 JAR 文件实际上包含组成应用程序的文件,但是考虑到安全性,不对这些文件进行仔细区分。Phar 扩展正是基于类似的理念,但是在设计时主要针对 PHP 的 Web 环境。同样,与 JAR 归档不同的是,Phar 归档可由 PHP 本身处理,因此不需要使用额外的工具来创建或使用。

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

创建 Phar

创建 Phar 文件需要执行若干步骤。所有步骤需要用到某种形式的 PHP 命令完成创建,因为不存在用于创建归档的独立工具。此外,要创建和修改 Phar 文件,php.ini 设置 phar.readonly 必须被设置为 0。在 PHP 的 Phar 归档内打开和引用文件时不需要使用到该设置。

让我们看一看创建可用于驱动应用程序的 Phar 文件需要哪些步骤。应用程序的设计目标是从 Web 浏览器或命令提示符直接加载。第一步是创建 Phar 文件,因此我们将创建清单 1 所示的
Phar
对象。对象引用将允许您控制 Phar 归档的所有方面。

清单 1. 创建
Phar
对象

$p = new Phar('/path/to/my.phar', CURRENT_AS_FILEINFO | KEY_AS_FILENAME, 'my.phar');
$p->startBuffering();

构造函数的第一个参数表示保存 Phar 文件的位置。第二个参数将所有参数都传递给
RecursiveDirectoryIterator
父类。第三个参数是在流上下文中引用 Phar 归档的别名。因此对于清单 1,可以在这个 Phar 归档中使用 phar://my.phar 引用文件。您还可以发出
Phar::startBuffering()
方法调用来缓冲对归档做出的修改,直到发出
Phar::stopBuffering()
命令为止。尽管不一定要执行上述操作,但是这样做确实改善了创建或修改归档的性能,因为它避免了每次在脚本中修改归档时对做出的修改进行保存。

默认情况下,创建的 Phar 将使用原生的基于 Phar 的归档格式。还可以按照清单 2 所示将格式转换为 ZIP 格式,从而对 Phar 文件使用 ZIP 或 TAR 格式。

清单 2. 将存储格式转换为 ZIP 格式
$p = $p->convertToExecutable(Phar::ZIP);

转换归档格式有利也有弊。主要优点就是能够使用任何处理 ZIP 或 TAR 文件的工具查看归档的内容。然而,如果 Phar 归档没有使用原生的基于 Phar 的归档格式,那么它不需要使用 Phar 扩展加载归档,而使用 ZIP 或 TAR 格式的 Phar 归档则需要如此。

接下来,将需要定义文件存根(stub),这是在加载 Phar 文件时首先调用的代码。

回页首

Phar 文件存根

文件存根仅仅是在加载 Phar 文件时最初运行的代码的一小部分,并且始终以一个
__HALT_COMPILER()
标记作为结束。清单 3 展示了一个典型的文件存根。

清单 3. Phar 文件存根
<?php
Phar::mapPhar();
include 'phar://myphar.phar/index.php';
__HALT_COMPILER();

上面所示的
Phar::mapPhar()
方法调用通过读取清单文件(manifest)对 Phar 归档执行初始化。您需要在归档内引用文件之前使用 phar:// 流包装器执行初始化。初始加载的文件将是应用程序首次加载时的文件;在本例中为 index.php。

如何将这个文件存根 Phar 添加到 Phar 归档取决于所使用的归档的格式。对于基于 Phar 的归档,使用
Phar::setStub()
方法,它将接受 PHP 代码的惟一参数,并以字符串形式放入存根中。清单 4 演示了这一方法。

清单 4. 使用
Phar::setStub()
创建文件存根

$p->setStub('<?php Phar::mapPhar();
include 'phar://myphar.phar/index.php'; __HALT_COMPILER(); ?>');

如果您计划使用存根而不是重定向到 index.php 页面来完成操作,可以使用 helper 方法
Phar::createDefaultStub()
构建文件存根。因此,只需要传递您希望包含在文件存根的文件的名称。在清单 5 中,将重写
Phar::setStub()
方法调用来使用 helper 方法。

清单 5. 使用
Phar::createDefaultStub()
创建文件存根

$p->setStub($p-> createDefaultStub('index.php'));

如果从 Web 服务器加载 Phar,
Phar::createDefaultStub()
方法的第二个可选参数允许包含一个不同的文件。这对于设计用于命令行或 Web 浏览器上下文的应用程序非常方便。

对于基于 ZIP 和 TAR 的实现,将以上存根的内容存储到 .phar/stub.php 文件内,而不是使用
setStub()
命令。

回页首

将文件添加到归档

Phar
对象使用
ArrayAccess
SPL 对象,允许以数组的形式访问归档内容,因此提供了许多方法来向归档添加文件。最简单的方法是直接使用
ArrayAccess
接口。

清单 6. 向归档添加文件
$p['file.txt'] = 'This is a text file';
$p['index.php'] = file_get_contents('index.php');

清单 6 表明文件名被指定为数组键,将内容指定为值。可以使用
file_get_contents()
函数获得现有文件的内容,然后将内容设为值。这样可以更加灵活地向归档添加文件,可以通过引用现有文件或动态构建文件实现。后一种方法可以作为应用程序构建脚本的一部分。

如果存储在 Phar 归档中的文件非常大,可以分别通过
PharFileInfo::setCompressedGZ()
PharFileInfo::setCompressedBZIP2()
方法使用 gzip 或 bzip2 压缩有选择地压缩归档中的文件。在清单 7 中,您将使用 bzip2 压缩文件。

清单 7. 使用 bzip2 压缩 Phar 归档中的文件
$p['big.txt'] = 'This is a big text file';
$p['big.txt']->setCompressedBZIP2();

要压缩文件或使用包含压缩文件的归档,必须在 PHP 安装中支持 bzip2 或 zlib(用于 gz 压缩文件)扩展。

假设您需要将许多文件加入到归档中。使用
ArrayAccess
接口逐一添加文件是一项非常单调的工作,因此可以使用一些便捷的方法。一种方法就是使用
Phar::buildFromDirectory()
方法,该方法将遍历指定的目录并添加其中的文件。它还支持对添加的文件进行过滤,方法是使用文件的正则表达式模式传递第二个参数,以匹配文件并添加到归档中。清单 8 展示了这一过程。

清单 8. 使用
Phar::buildFromDirectory()
向归档添加文件

$p->buildFromDirectory('/path/to/files','./\.php$/');

清单 8 将指定目录中的 PHP 文件添加到 Phar 归档。如果需要对添加的文件执行任何修改,比如将文件压缩,那么可以使用
ArrayAccess
接口返回。

可以使用一个迭代器(iterator)通过
Phar::buildFromIterator()
方法添加文件。支持两种风格的迭代器:一种是将 Phar 中的文件名映射到磁盘文件的名称,另一种是返回
SplFileInfo
对象。
RecursiveDirectoryIterator
是一种兼容的迭代器,下面展示如何使用它向归档添加目录文件。

清单 9. 使用
Phar::buildFromIterator()
向归档添加目录文件

$p->buildFromIterator(new RecursiveIteratorIterator
(new RecursiveDirectoryIterator('/path/to/files')),'/path/to/files');

Phar::buildFromIterator()
方法接受迭代器对象本身作为惟一的参数。在上例中,您已经使用
RecursiveIteratorIterator
对象包装了
RecursiveDirectoryIterator
对象,
RecursiveIteratorIterator
对象提供了
Phar::buildFromIterator()
方法所需的兼容型迭代器。

我们现在已经创建了一个 Phar 归档,它可以用于任何 PHP 应用程序。让我们看一看如何方便地使用这个归档。

回页首

使用 Phar 归档

Phar 归档的一个优点就是可以非常方便地集成到任何应用程序中。如果使用的是原生的基于 Phar 的归档格式,这一点尤其明显。在这种情况下,您甚至不需要安装 Phar 扩展,因为 PHP 天生就可以加载文件并提取文件内容。基于 ZIP 和 TAR 的归档需要加载 Phar 扩展。

Phar 归档在设计时被包括到应用程序中,跟普通的 PHP 文件一样,这使得已经熟悉如何包含其他第三方代码的应用程序开发人员可以非常方便地使用 Phar 归档。让我们看一看在应用程序中集成 Phar 有多么容易。

回页首

在应用程序中集成 Phar 归档代码

在 Phar 归档中集成代码的最简单方法就是包含 Phar 归档,然后在 Phar 文件中包含需要使用的文件。phar:// 流包装器可以用来访问已加载 Phar 归档中的文件,如下所示。

清单 10. 在 Phar 归档中加载代码
include 'myphar.phar';
include 'phar://myphar.phar/file.php';

第一个 include 将加载 myphar.phar 归档,包含文件存根中指定的代码。第二个 include 使用流包装器打开 Phar 归档并且仅在归档中包括指定的文件。注意在归档中包含文件之前,您不需要包含 Phar 归档本身,如清单 10 所示。

回页首

从 Phar 归档运行 PHP 应用程序

Phar 归档的一个出色特性就是可以使用一个 Phar 归档打包整个应用程序并进行发布。这种方法的优点就是简化应用程序部署并且不会降低性能,它主要得益于 PHP V5.3 中新增的若干 Phar 增强。然而,设计在 Phar 中运行的应用程序时应当考虑以下几点:

任何需要创建的特定于应用程序实例的文件,比如 config 文件,都不能作为归档的一部分,因此需要将它们写入到独立但是可访问的位置。如果应用程序创建构成扩展的缓存文件,那么这些文件也要采用相同的做法。

您应当始终使用基于 Phar 的归档格式,并且不对归档中的文件进行压缩,从而获得最大的灵活性。基于 ZIP 和 TAR 的归档要求在 PHP 中安装 Phar 扩展,而基于 Phar 的归档甚至可用于未安装 Phar 扩展的情况。

应用程序中的任何文件引用都需要修改为同时使用 phar:// 流包装器和归档名,如前面小节所示。

PHPMyAdmin 是一种流行的 PHP 应用程序,它一直使用 Phar 打包,演示出使用 Phar 归档的简便性(参见 参考资料)。它一直以来被设计为从 Phar 归档文件运行,但是仍然能够在 Phar 归档之外存储配置文件。

回页首

结束语

Phar 归档是 PHP V5.3 中新增的非常方便的特性。它们能够在归档中打包 PHP 代码,这对通过单个文件发布应用程序或库有很大帮助。Phar 归档可以通过 require 或 include 函数轻松地从 PHP 文件加载,或者通过使用名称指定 Phar 归档,直接从浏览器或命令行执行。

参考资料

学习

您可以参阅本文在 developerWorks 全球网站上的 英文原文

阅读 “PHP V5 迁移指南”,了解如何将使用 PHP V4 开发的代码迁移到 V5 中。

将 PHP 应用程序连接到 Apache Derby” 展示了如何在 Windows® 上安装和配置 PHP(其中一些步骤适用于 Linux®)。

要了解有关使用 PHP 编程的 developerWorks 系列教程,请查看 “学习 PHP,第 1 部分”,学习 PHP,第 2 部分学习 PHP,第 3 部分

PHP.net 是 PHP 开发人员的主要参考资料。

查看 “推荐 PHP 读物列表”。

浏览 developerWorks 上的所有 PHP 内容

通过查阅 IBM developerWorks 的 PHP 项目资源 提高您的 PHP 技能。

要收听针对软件开发人员的有趣访谈和讨论,请查看 developerWorks podcasts

要将数据库与 PHP 结合使用吗?请查看 Zend Core for IBM,它是一个开箱即用的无缝 PHP 开发和生产环境,易于安装并且支持 IBM DB2 V9。

随时关注 developerWorks 的 技术活动和网络广播

查阅最近将在全球举办的面向 IBM 开放源码开发人员的研讨会、交易展览、网络广播和其他 活动

访问 developerWorks 开放源码专区,获得丰富的 how-to 信息、工具和项目更新,帮助您用开放源码技术进行开发,并与 IBM 产品结合使用。

查看免费的 developerWorks On demand demos,观看并了解 IBM 及开源技术和产品功能。

获得产品和技术

PHPMyAdmin 是一个流行的使用 Phar 打包的 PHP 应用程序,可以用来演示使用 Phar 归档的方便性。

获得 PHP V5.2.6

使用 IBM 试用软件 改进您的下一个开发项目,这些软件可以通过下载或从 DVD 获得。

下载 IBM 产品评估版,并开始使用来自 DB2®、Lotus®、Rational®、Tivoli® 和 WebSphere® 的应用程序开发工具和中间件产品。

讨论

参与 developerWorks blogs 并加入 developerWorks 社区。

加入 developerWorks PHP 论坛:使用 IBM Information Management 产品开发 PHP 应用程序(DB2,IDS)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐