使用phar上线你的代码包

在我前一阵子写的一篇文章《新版 SegmentFault 重构之系统架构》中,很多人对其中提到的利用phar上线代码比较感兴趣,我就在这边跟大家分享下我目前的做法。

哪些项目适合phar打包上线?

其实这种方法没有什么特别的限制,只有一条,你的程序是单一入口的,对web项目也就是说,所有的http请求都只有一个php文件作为处理方(大多数程序就是index.php)。

如果你的程序结构是这样的,那么基本可以无障碍切换到这种上线模式。实际上绝大多数现代的php框架构建的项目都是单一入口的结构了。

现有代码需要做何处理吗?

如果你的代码结构比较科学(比如采用大部分框架的推荐结构),那么一行都不需要改变。只有几个需要注意

  1. 在项目里用include或者require来引用其他项目内文件时,最好不要直接用相对地址,而是在前面加上__DIR__常量
  2. 因为phar包只能解析代码文件,所以建议静态文件单独部署

OK,准备工作做完后,我们就可以开始看看具体怎么部署了。为了方便大家了解,我在github上放了一个非常简单的小例子,它的地址是

https://github.com/SegmentFault/phar-sample

从一个简单的例子说起

这个例子的代码结构跟我们大多数项目很像,实际上我就是刻意模拟这些项目的代码结构
注意,运行这个项目最好在php 5.4以上的环境中

目录结构

  • app存放主要的逻辑代码,比如controller, model, service 等等
  • lib存放一些库文件,包括第三方的
  • portal其实就是项目的主入口了,打开你回发现里面只有一个文件index.php,这就是我前面提到的单一入口结构
  • static存放的是静态文件,比如js, css, 图片等等,这个目录需要你单独部署,我们的phar包里不会打包里面的内容,放在这里只是为了完整地展示一个项目结构
  • build.php文件就是我们的打包脚本了

如果你的项目需要模版文件,可能还需要一个template目录,在这里我就省略掉了

在浏览器里访问你的项目地址/portal/index.php,即可看到熟悉的Hello World!字样

这个项目中最重要的就是build.php这个文件了,它展示了一个经过简化的打包过程,实际上,稍加修改它就能用在你的项目中,这个文件的代码注释很详细,我就不重复说明了,现在我们在终端下运行它

phar1

啊哦,貌似出了点问题,不过不要紧,这是php的一个选项没有设置导致的,打开php.ini文件,找到;phar.readonly = On这一行,把前面的分号;去掉,然后把后面的On改为Off,然后保存再执行这个命令

phar2

看来成功了,而且当前目录下已经有了Sample.phar这个打包好的文件

如何部署phar文件

现在你一定对着这个phar文件感到新奇,但是又不知道如何用它,WTF!但是等等,请回到终端下执行命令

php Sample.phar

怎么样,现在你的整个项目就已经被包含在这个Sample.phar文件里了,而且它还能直接被执行,很神奇吧,那么我们应该怎么部署它呢?

以下是我的建议

首先为每次打包的文件生成一个版本号,比如你可以在build.php加上一行

rename('Sample.phar', 'Sample.' . date('Ymd.His') . '.phar');

这样每次打包后的文件就变成了类似Sample.20141111.123456.phar,而且不会重复,生成不重复id的方法有很多种,我推荐这种是因为它可以方便你看到打包时间,以后你做回滚的时候就可以知道要回滚到那个时间的版本,当然你也可以把这个版本跟你的SCM版本关联起来

然后,在线上使用另外一个入口文件引用这个包,比如线上的入口目录/wwwroot下的index.php文件有如下代码

require __DIR__ . '/../packages/Sample.20141111.123456.phar';

是的,只有一行就这么简单!packages就是你存放这些打包好文件的目录,你可以随意放置。

我说的这些步骤都可以很方便的写成脚本集成到你目前的自动化部署流程中。

以上的文字只是抛砖引玉,欢迎大家对这个方案提出意见,并对它做一些性能测试,如果你运行在5.5以上的版本(默认打开opcache),几乎对性能没有影响。


程序员就要好好玩
我的生涯一片无悔,想起那天夕阳下的奔跑,那是我逝去的青春aaaaa
avatar
joyqi
SegmentFault CTO,Typecho 作者

我的生涯一片无悔,想起那天夕阳下的奔跑,那是我逝去的青春

16.1k 声望
2.3k 粉丝
0 条评论
推荐阅读
为我们的 10 周年喝彩
10 年前,我和高阳及董锋在北京参加了中国第一届黑客马拉松。以开发者为中心的活动在当时还是个新鲜事物,我们第一次看到了这个群体中所蕴含的巨大能量,以至于它对我们后面的创业决定也产生了巨大的影响。活动结...

joyqi49阅读 22k评论 161

怎样用 PHP 来实现枚举?
在数学和计算机科学理论中,一个集的枚举是列出某些有穷序列集的所有成员的程序,或者是一种特定类型对象的计数。这两种类型经常(但不总是)重叠。枚举是一个被命名的整型常数的集合,枚举在日常生活中很常见,...

唯一丶25阅读 6.4k评论 4

PHP转Go实践:xjson解析神器「开源工具集」
我和劲仔都是PHP转Go,身边越来越多做PHP的朋友也逐渐在用Go进行重构,重构过程中,会发现php的json解析操作(系列化与反序列化)是真的香,弱类型语言的各种隐式类型转换,很大程度的减低了程序的复杂度。

王中阳Go10阅读 1.7k评论 2

封面图
图片防盗链破解 解决图片防盗链问题 反向代理
当客户端(浏览器)向服务器请求内容的时候,会提交一个header,这个header中包含了如:浏览器信息、cookie等内容,那么有一个叫referer的东东,也包含在这里面。

TANKING7阅读 11.3k评论 5

Git操作不规范,战友提刀来相见!
年终奖都没了,还要扣我绩效,门都没有,哈哈。这波骚Git操作我也是第一次用,担心闪了腰,所以不仅做了备份,也做了笔记,分享给大家。问题描述小A和我在同时开发一个功能模块,他在优化之前的代码逻辑,我在开...

王中阳Go5阅读 2.2k评论 2

封面图
微信公众号开发:自动回复文本/图片/图文消息/关键词回复/上传素材/自定义菜单
对接流程1、申请微信公众号测试账号URL:[链接]2、登录,配置开发者服务器URL和Token开发者服务器配置代码:config.php {代码...} URL是config.php在你服务器的URLToken是上面代码自己设置的Token搞定之后,就能完...

TANKING2阅读 10.1k

Ajax实现搜索联想 搜索关键词提醒 无刷新搜索
通过javascript监听搜索框的内容,调用后端即可。(1)javascript监听搜索框的内容(2)把搜索框的关键词传给后端进行搜索(3)搜索到结果,遍历到页面

TANKING1阅读 4.4k

avatar
joyqi
SegmentFault CTO,Typecho 作者

我的生涯一片无悔,想起那天夕阳下的奔跑,那是我逝去的青春

16.1k 声望
2.3k 粉丝
宣传栏