質問

I'm trying to make my PHAR archive marked as PHP (I don't know correct term for this) so that I can use it from cli without php part. So instead of calling php /path/to/my/archive.phar ARGUMENTS_HERE I can just move it to /usr/local/bin and call it archive from anywhere. (Just like PHPUnit or Composer).

If I'm right, to do that, I just need to add #!/usr/bin/env php on top of my PHAR archive file?

How do I do that? I tried to mimic composer compiler in my build script, but it just crashes PHP_CLI (segmentation fault):

$archiveName = 'phpbenchmark.phar';

$phar = new Phar($archiveName);

$phar->buildFromDirectory(__DIR__, '/\/lib\/|\/vendor\//');

$phar->setStub(createStub());

function createStub()
{
    $stub = <<<EOD
#!/usr/bin/env php
<?php
Phar::mapPhar('phpbenchmark.phar');
require 'phar://phpbenchmark.phar/lib/app.php';
__HALT_COMPILER();
EOD;
    return $stub;
}

As you can see, I only need stub to run /lib/app.php file and that's it.

Prepending to compiled PHAR

Of course, first thing I tried was manually prepending it to my archive, but it looks like that corrupts it:

PHP Fatal error:  Uncaught exception 'PharException' with message 'manifest cannot be larger than 100 MB in phar "/home/igor/Dropbox/www/Github/PIFlexPHPBenchmark/phpbenchmark.phar"' in /home/igor/Dropbox/www/Github/PIFlexPHPBenchmark/phpbenchmark.phar:9
Stack trace:
#0 /home/igor/Dropbox/www/Github/PIFlexPHPBenchmark/phpbenchmark.phar(9): Phar::webPhar(NULL, 'index.php')
#1 {main}
  thrown in /home/igor/Dropbox/www/Github/PIFlexPHPBenchmark/phpbenchmark.phar on line 9

Fatal error: Uncaught exception 'PharException' with message 'manifest cannot be larger than 100 MB in phar "/home/igor/Dropbox/www/Github/PIFlexPHPBenchmark/phpbenchmark.phar"' in /home/igor/Dropbox/www/Github/PIFlexPHPBenchmark/phpbenchmark.phar on line 9

PharException: manifest cannot be larger than 100 MB in phar "/home/igor/Dropbox/www/Github/PIFlexPHPBenchmark/phpbenchmark.phar" in /home/igor/Dropbox/www/Github/PIFlexPHPBenchmark/phpbenchmark.phar on line 9

Call Stack:
    0.0010     306272   1. {main}() /home/igor/Dropbox/www/Github/PIFlexPHPBenchmark/phpbenchmark.phar:0
    0.0011     307840   2. Phar::webPhar() /home/igor/Dropbox/www/Github/PIFlexPHPBenchmark/phpbenchmark.phar:9

Note that exactly the same archive works before I manually modify it. (But needs php /path/to/arch of course)

役に立ちましたか?

解決

Aaaand, solved (kinda) after few hours of breaking my head. I still have no idea why, this build script seems to work:

$archiveName = 'phpbenchmark.phar';

$phar = new Phar($archiveName);

$phar->buildFromDirectory(__DIR__, '/\/lib\/|\/vendor\//');

$phar->setStub(createStub());

function createStub()
{
    $stub = <<<ENDSTUB
#!/usr/bin/env php
<?php
Phar::mapPhar('phpbenchmark.phar');
require 'phar://phpbenchmark.phar/lib/app.php';
__HALT_COMPILER();
ENDSTUB;

    return $stub;
}

Except.....I can't really see any differences to original script posted in my question? Why would original one crash PHP Cli and this one works?

他のヒント

All I needed to do to get that to work is update the line:

$phar->setStub($phar->createDefaultStub("main.php"));

to :

$phar->setStub("#!/usr/bin/env php\n\n" . $phar->createDefaultStub("main.php"));

This takes the default stub that phar creates for you, and adds the requires #! line to it. Then just chmod 700 the resulting phar file, and you are good to go.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top