Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP Phar - file_exists() issue

My Phar script creates a new file with fwrite, which works fine, it creates the new file outside the phar, in the same directory as the phar file.

But then when i use if(file_exists('file.php')) it doesn't pick it up.

But then include and require do pick it up.

Anyone know about this problem? Been testing and researching for a while a can't seem to find a solution.

like image 305
Lan Avatar asked Aug 20 '13 01:08

Lan


3 Answers

Working with file paths and Phar archives

Working with file paths and Phar archives in PHP can be tricky. The PHP code inside of a Phar file will treat relative paths as being relative to the Phar archive, not relative to the current working directory. Here's a short example:

Say you have the following files:

phar/index.php
test.php
my.phar

The index.php file is located inside of the phar directory. It is the bootstrap file for the phar archive:

function does_it_exist($file){
  return file_exists($file) ? "true" : "false";
}

The bootstrap file is executed when the phar file is included from a PHP script. Our bootstrap file will simply cause the function "does_it_exist" to be declared.

Let's try running different code inside of test.php and see what the results are for each run:

//Run 1:
require_once 'phar/index.php';  //PHP file
$file = __DIR__ . "/index.php"; //absolute path
echo does_it_exist($file);      //prints "false"

//Run 2:
require_once 'phar/index.php';  //PHP file
$file = "index.php";            //relative path
echo does_it_exist($file);      //prints "false"

//Run 3:
require_once 'my.phar';         //phar file
$file = __DIR__ . "/index.php"; //absolute path
echo does_it_exist($file);      //prints "false"

//Run 4:
require_once 'my.phar';         //phar file
$file = "index.php";            //relative path
echo does_it_exist($file);      //prints "true"

Look at Run 4. This code includes the phar file and passes the function a relative path. Relative to the current working directory, index.php does not exist. But relative to the contents of the phar archive, it does exist, which is why it prints "true"!

like image 58
Vineet1982 Avatar answered Oct 07 '22 12:10

Vineet1982


At the PHAR's stub, you can use the __DIR__ magic constant to get the PHAR file's folder.

With that in mind, you can simply use

is_file(__DIR__ . DIRECTORY_SEPARATOR . $path);

To check for a file's existence outside the PHAR.

You can ONLY do this from the stub, and ONLY if it's a custom stub, as opposed to one generated by Phar::setDefaultStub(). If you need to check for files further down the line, you'll have to make that constant's value available somehow, like a global variable, a custom non-magical constant or a static property or something, which other files then consult with.

EDIT: Actually, you can also use dirname(Phar::running(false)) to get the PHAR's folder from anywhere in the PHAR. That function returns an empty string if you're not within a PHAR, so whether your application is executed as a PHAR or directly, it should work fine, e.g.

$pharFile = Phar::running(false);
is_file(('' === $pharFile ? '' : dirname($pharFile) . DIRECTORY_SEPARATOR) . $path)
like image 33
boen_robot Avatar answered Oct 07 '22 13:10

boen_robot


I meet the same issue today. After several hours digging ... I found the answer.

Can you try the following script first?

if(file_exists(realpath('file.php')));

If the file exist, then the issue is

if you use only the filename without path information, php treat file is related to phar stub. for example:

phar:///a/b/c/file.php

So, you have to use absolute path to manipulate the file, for example:

/home/www/d/e/f/file.php

Hope this help.

Mark

like image 45
Mark Wu Avatar answered Oct 07 '22 12:10

Mark Wu