Упаковка PHP-приложения

Я пытаюсь создать файл.phar из моего веб-приложения. Следуя примеру документации php, я попробовал следующее для этой цели.

<?php
$srcRoot = __DIR__ . "/../app";
$buildRoot = __DIR__ . "/../build";
$p = new Phar("$buildRoot/build.phar", 0, 'build.phar');
$p->buildFromIterator(
    new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($srcRoot)
    ),
    $srcRoot
);

Однако я получил следующую ошибку. Я не имею ни малейшего представления об ошибке. Что не так с кодом?

PHP Fatal error:  Uncaught exception 'UnexpectedValueException' with message
'Iterator RecursiveIteratorIterator returned a path "D:\site\app" that is
 not in the base directory "D:\site\app"'
in D:\site\tools\create-phar.php:7

4 ответа

Решение

Источник проблемы в том, что RecursiveDirectoryIterator также перечисляет точечные файлы - . а также .., При переборе /path/to/foo это также перечисляет /path/to/foo/. а также /path/to/foo/.. который идет в родительский каталог - за пределами базового каталога.

Таким образом, вы должны предотвратить включение файлов "..", чего легче всего добиться с FilesystemIterator::SKIP_DOTS в качестве второго параметра 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
);

Box позволяет очень легко создавать архивы PHAR из ваших исходных файлов. Обычно вы сначала добавляете файл конфигурации, а затем можете создать свой файл PHAR, просто вызвав box build в командной строке.

В Matthieu Moquet есть отличный пост, в котором рассказывается, как он использовал Box для упрощения распространения приложения PHP Cli. Лично я также использовал Box для приложения CLI, однако официальное описание проекта не ограничивается приложениями CLI, а скорее обобщает проект Box следующим образом:

Приложение для создания и управления Phars.

Проект Box предоставляет скрипт сборки PHAR и позаботится о правильной настройке всех путей, так что это может решить вашу проблему.

Решение, предложенное cweiske, великолепно. Однако в некоторых ситуациях может потребоваться возможность добавить дополнительные исключения пути к каталогу. Взгляните на этот пример, который исключает любые ссылки на.git каталог, используя FilterIterator:

// 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);

Взгляните на файл php.ini, чтобы проверить значение поля phar.readonly. Должно быть 0 для создания архива phar.

Ссылка: http://php.net/manual/en/phar.configuration.php

Другие вопросы по тегам