Как разместить файл phar внутри файла phar?

Я хотел бы поместить файл phar в файл phar. Я пробовал это наиболее прямолинейно:

$p = new Phar('test.phar', null, 'self.phar'); $p->setStub('<?php Phar::mapPhar(); include \'phar://self.phar/index.php\'; __HALT_COMPILER(); ?>'); $p['index.php'] = '<?php echo "hello world\n";'; $p = new Phar('test2.phar', null, 'self.phar'); $p->setStub('<?php Phar::mapPhar(); include \'phar://self.phar/index.php\'; __HALT_COMPILER(); ?>'); $p['index.php'] = '<?php echo "hello phar world\n";'; $p['test.phar'] = file_get_contents('test.phar'); 

Однако PHP просто не хочет его открывать. Он не принимает ни одно из следующих условий:

 // Warning: Phar::mapPhar(phar://path/to/test2.phar/test.phar): failed to open // stream: Invalid argument in phar://path/to/test2.phar/test.phar include('phar://test2.phar/test.phar'); // Warning: include(phar://test2.phar/test.phar/index.php): failed to open // stream: phar error: "test.phar/index.php" is not a file in phar "test2.phar" include('phar://test2.phar/test.phar/index.php'); // Warning: include(phar://test2.phar/phar://test.phar/index.php): failed to // open stream: phar error: "phar:/test.phar/index.php" is not a file in phar // "test2.phar" include('phar://test2.phar/phar://test.phar/index.php'); в // Warning: Phar::mapPhar(phar://path/to/test2.phar/test.phar): failed to open // stream: Invalid argument in phar://path/to/test2.phar/test.phar include('phar://test2.phar/test.phar'); // Warning: include(phar://test2.phar/test.phar/index.php): failed to open // stream: phar error: "test.phar/index.php" is not a file in phar "test2.phar" include('phar://test2.phar/test.phar/index.php'); // Warning: include(phar://test2.phar/phar://test.phar/index.php): failed to // open stream: phar error: "phar:/test.phar/index.php" is not a file in phar // "test2.phar" include('phar://test2.phar/phar://test.phar/index.php'); в // Warning: Phar::mapPhar(phar://path/to/test2.phar/test.phar): failed to open // stream: Invalid argument in phar://path/to/test2.phar/test.phar include('phar://test2.phar/test.phar'); // Warning: include(phar://test2.phar/test.phar/index.php): failed to open // stream: phar error: "test.phar/index.php" is not a file in phar "test2.phar" include('phar://test2.phar/test.phar/index.php'); // Warning: include(phar://test2.phar/phar://test.phar/index.php): failed to // open stream: phar error: "phar:/test.phar/index.php" is not a file in phar // "test2.phar" include('phar://test2.phar/phar://test.phar/index.php'); 

Я знаю, что конструктивность этого вопроса ограничена, потому что он может просто не работать с phar-in-phar, но, вероятно, я просто пропустил способ, как это сделать, и я просто не вижу дерева для деревьев.

Функция, которую вы должны использовать для загрузки phar-файла в PHP, это Phar :: loadPhar, например

 Phar::loadPhar("test2.phar", "test2"); 

Сделал бы файл ph2 test2.phar загружен и доступен через alias test2, поэтому вы могли бы включить в него файлы:

 include ('phar://test2/index.php'); 

Однако, похоже, что это не работает, если этот файл находится внутри самого phar. Код PHP для loadPhar:

 fp = php_stream_open_wrapper(fname, "rb", IGNORE_URL|STREAM_MUST_SEEK, &actual); 

и, по-видимому, флаг IGNORE_URL делает невозможным открытие файла.

Существует обходной путь – извлечение файла phar, который содержится внутри другого phar, во временный файл, а затем, по-видимому, он может быть загружен без каких-либо проблем. Следующий код будет извлекать файл phar (phar1.phar), который содержится во втором файле phar, а затем вызывает loadPhar.

 function extractAndLoadPhar(){ $tempFilename = tempnam( sys_get_temp_dir() , "phar"); $readHandle = fopen("phar://phar2/phar1.phar", "r"); $writeHandle = fopen($tempFilename, "w"); while (!feof($readHandle)) { $result = fread($readHandle, 512); fwrite($writeHandle, $result); } fclose($readHandle); fclose($writeHandle); $result = Phar::loadPhar($tempFilename, "phar1"); } extractAndLoadPhar(); //Extract and load the phar include ('phar://phar1/src1.php'); //It can now be referenced by 'phar1' 

Я разместил рабочую копию этого кода здесь https://github.com/Danack/pharphar, который создает phar, вставляет его во 2-й фар, а затем загружает и вызывает функцию из 1-го фара внутри второго phar.

Отметим – я не уверен, что эта техника – хорошая идея. Кажется, есть некоторая двусмысленность (иначе я не понимаю), что происходит с файлами-заглушками для каждого из файлов phar. т.е. они оба загружаются, или это просто внешний файл phar, который загружен и запущен.