Я экспериментирую в создании инструментов CLI с помощью библиотеки консоли Symfony2. У меня есть что-то основное, и теперь я хочу упаковать его как phar. Я прочитал несколько примеров, но те, которые я видел, очень просты (3 файла, без пространств имен и т. Д.).
В моем каталоге src/
меня есть следующее:
Выше src/
У меня есть console.php
который я запускаю для запуска приложения. У меня также есть vendors/
dir, поскольку я использую компоновщик для установки зависимостей. console.php
очень прост:
#!/usr/bin/env php <?php set_time_limit(0); $loader = require 'vendor/autoload.php'; use Symfony\Component\Console\Application; use Bendihossan\Pinfo\Command\EnvironmentCommand; use Bendihossan\Pinfo\Command\ExtensionsCommand; use Bendihossan\Pinfo\Command\RunAllCommand; $console = new Application(); $console->add(new RunAllCommand()); $console->add(new EnvironmentCommand); $console->add(new ExtensionsCommand); $console->run();
Из чего (мало) я понимаю, что нужно построить phar, я думаю, что мне нужно включить console.php
в качестве заглушки и все остальное в src/
plus всех моих зависимостей в vendors/
.
Если посмотреть на пример кода на phpmaster.com, то они будут указывать каждый файл вручную для включения в phar с помощью file_get_contents
, но мне нужно поддерживать структуру каталогов, чтобы использовать автозагрузчик композитора и поддерживать структуру каталогов PSR-0.
Есть ли простой способ создать .phar и поддерживать структуру каталогов внутри него, чтобы я мог использовать автозагрузчик композитора?
Я предлагаю вам взглянуть на Compiler
Composer (он был создан Фабием Потеньером в Силексе). В этом классе вы можете увидеть, как большое консольное приложение, например Composer, создает файл .phar
.
Некоторые интересные части:
// line 49 $phar = new \Phar($pharFile, 0, 'composer.phar'); $phar->setSignatureAlgorithm(\Phar::SHA1); $phar->startBuffering();
Phar#startBuffering
начинает создание файла Phar#startBuffering
.
// Line 54 $finder = new Finder(); $finder->files() ->ignoreVCS(true) ->name('*.php') ->notName('Compiler.php') ->notName('ClassLoader.php') ->in(__DIR__.'/..')
Здесь Composer использует компонент Symfony2 Finder для поиска каждого файла в каталоге src
(кроме этого файла и автозагрузчика).
// Line 63 foreach ($finder as $file) { $this->addFile($phar, $file); }
Здесь Composer выполняет итерацию по каждому найденному файлу и добавляет его в архив Phar. (вы можете увидеть метод Compiler#addFile
в строке 116 ).
Это повторяется несколько раз. А затем на линии 93 используется автозагрузчик Composer:
$this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/autoload.php')); $this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/autoload_namespaces.php')); $this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/autoload_classmap.php')); $this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/autoload_real.php'));
Поскольку Phar является потоком, структура каталогов хранится в файле phar, а автозагрузчик Composer все еще может загружать классы.
Затем, в конце, заглушки добавляются и буферизация останавливается:
$phar->setStub($this->getStub()); $phar->stopBuffering();
(см. метод Compiler#getStub
по строке 173 ). Метод Phar#stopBuffering
останавливает создание phar и сохраняет его в phar-файле.
Чтобы завершить эту историю, Composer создает очень простой файл компиляции CLI, который выполняет эту команду.