Упаковка 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.