打包PHP应用程序

打包PHP应用程序,php,deployment,build,phar,Php,Deployment,Build,Phar,我正在尝试从我的web应用程序创建一个.phar文件。为了这个目的,我尝试了以下方法 <?php $srcRoot = __DIR__ . "/../app"; $buildRoot = __DIR__ . "/../build"; $p = new Phar("$buildRoot/build.phar", 0, 'build.phar'); $p->buildFromIterator( new RecursiveIteratorIterator( new

我正在尝试从我的web应用程序创建一个.phar文件。为了这个目的,我尝试了以下方法

<?php
$srcRoot = __DIR__ . "/../app";
$buildRoot = __DIR__ . "/../build";
$p = new Phar("$buildRoot/build.phar", 0, 'build.phar');
$p->buildFromIterator(
    new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($srcRoot)
    ),
    $srcRoot
);
使从源文件创建PHAR存档变得非常容易。基本上,您首先添加一个配置文件,然后只需在命令行上调用
box build
即可创建PHAR文件

Matthieu Moquet的一篇文章描述了他如何使用Box简化PHP Cli应用程序的分发。就我个人而言,我也曾在CLI应用程序中使用过Box,但官方项目说明并不限于CLI应用程序,而是将Box项目概括为:

用于构建和管理Phar的应用程序


Box项目提供PHAR构建脚本并负责正确设置所有路径,因此这可能会解决您的问题。

查看php.ini文件以检查PHAR.readonly字段的值。 必须为0才能创建phar存档


参考:

问题的根源是,它还列出了点文件-
。 当在
/path/to/foo
上迭代时,它还列出了
/path/to/foo/
/path/to/foo/。
,这两个目录位于基本目录之外的父目录

因此,您必须防止包含“.”文件,这是作为DirectoryIterator的第二个参数最容易实现的:

new RecursiveDirectoryIterator($srcRoot, FilesystemIterator::SKIP_DOTS)
(@cweiske--我刚意识到你比我先到了,我会确保下次刷新页面,我最真诚的道歉!)

只需稍加编辑即可跳过unix路径/。和/:

<?php
$srcRoot = __DIR__ . "/../app";
$buildRoot = __DIR__ . "/../build";
$p = new Phar("$buildRoot/build.phar", 0, 'build.phar');
$p->buildFromIterator(
    new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($srcRoot, FilesystemIterator::SKIP_DOTS)
    ),
    $srcRoot
);
提出的解决方案非常出色。但是,在某些情况下,您可能需要能够添加更多目录路径排除。看看这个示例,它使用
filterierator
,排除了对
.git
目录的任何引用:

// create phar
$p = new Phar($pharFile, 0, $pharFile);

// produce iteration which excludes any references to values assigned to $excludes
$iterator = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS)
);
$filter = new class($iterator) extends FilterIterator {
    public static $excludes = [];
    public function accept()
    {
        $item = $this->current();
        $actual   = 0;
        foreach (self::$excludes as $exclude) {
            $actual += (int) boolval(strpos($item->getPath(), $exclude));
        }
        return ($actual === 0);
    }
};
$filter::$excludes = ['.git'];

$p->buildFromIterator($filter, $path);


谢谢FaKell,我试过Box,它实际上生成了一个PHAR文件。然而,phar存档中的文件似乎无法包含非phar文件。有什么解决方法吗?您确定错误源于Box项目吗?您是否曾经成功地为正在工作的项目创建过PHAR文件?如果不是,那么已知PHP在文件方面存在问题。您是如何尝试包含这些文件的?我想知道为什么文档示例中没有提到这一点。如果没有这个选项,它会工作吗?可能在某些PHP版本中更改了默认标志。昨天我在手册中添加了一条注释。@cweiske提出的解决方案非常出色!如果需要更多排除,也可以插入FilterEditor。见下面我的答案。
// create phar
$p = new Phar($pharFile, 0, $pharFile);

// produce iteration which excludes any references to values assigned to $excludes
$iterator = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS)
);
$filter = new class($iterator) extends FilterIterator {
    public static $excludes = [];
    public function accept()
    {
        $item = $this->current();
        $actual   = 0;
        foreach (self::$excludes as $exclude) {
            $actual += (int) boolval(strpos($item->getPath(), $exclude));
        }
        return ($actual === 0);
    }
};
$filter::$excludes = ['.git'];

$p->buildFromIterator($filter, $path);