BeWithYou

胡搞的技术博客

  1. 首页
  2. PHP
  3. 使用迭代器打包phar

使用迭代器打包phar


当你的项目符合单点入口,即所有请求都以index.php作为入口时,可以考虑使用phar打包代码。可能会方便线上部署,就跟java的jar一样。虽然现在很少看到有人这么做了,不过可以学习一下。

打包phar的核心类是Phar类,网上的例子大多数是这样的:

//前略 file name:build.php
$file = "test.phar";
$phar = new Phar(__DIR__.'/'.$file,  FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::KEY_AS_FILENAME, $file);
//开始打包
$phar->startBuffering();
//添加进去
$phar->buildFromDirectory(__DIR__, '/\.php$/');
$phar->buildFromDirectory(__DIR__, '/\.tpl$/');
//删除本身
$phar->delete('build.php');
//设置入口
$phar->setStub("<?php
Phar::mapPhar('{$file}');
require 'phar://{$file}/index.php';
__HALT_COMPILER();
?>");

然后使用php build.php就可以打包成指定的phar文件。使用时可以php test.phar即可。也可以require "test.phar";

需要注意的是,项目内部使用的php文件互相引用,最好使用绝对路径__DIR__的方式。

这种方法使用指定目录文件的方式加载,可能不够灵活。这里提供一种使用目录迭代器的方式打包phar,省去了手动指定目录的步骤。

//先检查php.ini的配置 是否允许打包phar
if(ini_get('phar.readonly')==='1') {
    throw new Exception('Please set phar.readonly to Off');
}
//检查运行环境是否是命令行
if(php_sapi_name()==='cli'){
    $file = basename(__DIR__).'.phar';
    new build($file, __DIR__);
}

//继承Phar类
class build extends Phar
{
    function __construct($file, $source_dir)
    {
        if(is_file($file)) {
            unlink($file);
        }
        parent::__construct($file);
        //新建目录迭代器用来递归的遍历目录文件
        $folder = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source_dir));
        $items = [];
        foreach($folder as $item) {
            //排除掉不需要的文件和目录
            if(strpos($item->getPathName(), '/.git/')) {
                continue;
            }
            if(strpos($item->getPathName(), '.psd')) {
                continue;
            }
            if(strpos($item->getPathName(), '/test/')) {
                continue;
            }
            $filename = pathinfo($item->getPathName(), PATHINFO_BASENAME);
            if(substr($filename, 0, 1) != '.') {
                $items[substr($item->getPathName(), strlen($source_dir))] = $item->getPathName();
            }
        }
        $this->startBuffering();
        //使用buildFromIterator方法 而不是buildFromDirectory
        $this->buildFromIterator(new ArrayIterator($items));
        //删除本身
        $this->delete('build.php');

        $this->setStub("<?php
        if(is_file('phar://'.__FILE__.'/index.php')) {
            require 'phar://'.__FILE__.'/index.php';
        }
        __HALT_COMPILER();
        ?>");
        $this->stopBuffering();
    }
}
回到顶部