如何将phar文件放在phar文件中?

时间:2012-11-01 15:36:05

标签: php 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');

我知道这个问题的建设性是有限的,因为它可能不适用于phar-in-phar但是我可能只是错过了一种方法如何做到这一点而我只是没有看到树木。

1 个答案:

答案 0 :(得分:4)

用于在PHP中加载phar文件的函数是Phar::loadPhar,例如

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

可以通过别名test2加载并访问phar文件test2.phar,因此您可以通过执行以下操作来包含文件:

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

但是,如果该文件位于phar本身内部,则似乎不起作用。 loadPhar的PHP代码是:

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

显然IGNORE_URL标志使文件无法打开。

有一种解决方法 - 将另一个phar中包含的phar文件解压缩到一个临时文件,然后显然可以毫无问题地加载它。以下代码将提取第二个phar文件中包含的phar文件(phar1.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,将其嵌入到第二个phar中,然后从第二个phar中的第一个phar加载并调用一个函数。

要注意 - 我不相信这种技术是个好主意。似乎有一些歧义(我不明白)每个phar文件的存根文件会发生什么。即它们是否都被加载,或者只是最外层的phar文件,它的存根被加载并运行。