Search code examples
phpphar

Should PHAR createDefaultStub differentiate between CLI and browser?


My question is about $indexfile and $webindexfile of createDefaultStub. My understanding was that $indexfile would be served up if the request is from the cli, and $webindexfile would be served up from a browser request.

I'm getting the same response ('backend') from either source, am I misunderstanding the behaviour? Or is my implementation wrong?

Thanks!

Directory Tree:

PHAR
+--app
    +--backend
        +--index.php //prints 'backend'
    +--frontend
        +--index.php //prints 'frontend'
+--build //destination for PHAR
+--build.php
+--index.php

/build.php

$phar = new Phar("build/app.phar", 0, "app.phar");
$phar->buildFromDirectory("./app");
$phar->setStub(
$phar->createDefaultStub(
    "backend/index.php", "frontend/index.php"
)

);

/index.php

include('phar://./build/app.phar');

From PHP manual:

createDefaultStub ([ string $indexfile [, string $webindexfile ]] )

Solution

  • My original post: Did you already try to run your phar file directly from the browser? (If your webserver does not recognize your .phar file as a php file, you can temporarily rename it to .php).

    You will see that it will work. If your url was http://localhost/phar/build/app.phar it will redirect to http://localhost/phar/build/app.phar/frontend/index.php automatically. And from the cli, there is obviously no redirect, it will automatically use the backend/index.php file (this is the default in your phar file).

    This redirect behavior does not happen from your own index.php. (that is why you see the backend/index.php file in your frontend too, this was the default) You have to build the redirect part yourself.

    If you do build it yourself, you can reference to your backend/frontend files like so:

    include('phar://./build/app.phar/frontend/index.php');
    

    Note, that if you include your phar file like that in another file, php sees it as a library phar file, rather than a complete application phar file [1]. I think they did not take into account that you might want your library to have other behavior on the cli than from the webbrowser.

    [1] http://php.net/manual/en/phar.using.intro.php (first paragraph)

    Edit:

    Some more investigations show that you might have found a bug. There are 2 ways of running a phar inside php. One is using the stream wrapper phar (like you are doing) and one is using the code that is in the phar file that runs in case you don't have the phar stream wrapper.

    If you use the code that runs if you don't have the phar stream wrapper, it works like expected.

    Try this:

    • rename your phar to .php
    • use this index.php:

    code:

    stream_wrapper_unregister('phar');
    include('./build/app.php');
    

    You will see that it works as expected now (but slower since you are not using the build in stream wrapper anymore).