How to get the source path of a symbolic link in PHP?

I have several files in my web folder, including these two:

  • /mydocroot/include/somesubdir/include.inc.php
  • /mydocroot/include/settings.inc.php

where somesubdir is a symbolic link to another directory on my disk, to a path with the name: eh, let say / where / else .

Inside include.inc.php something like this is written:

<?php require_once "../settings.inc.php"; ?> 

In my opinion, this should include /mydocroot/include/settings.php ... But guess what happens: PHP is trying to include /anywhere/settings.inc.php , not /mydocroot/include/settings.inc.php .

PHP seems to automatically resolve symlinks.

How can I avoid this and include my settings.inc.php file?

+7
source share
4 answers

The most straightforward solution is to always use absolute paths. There are several ways to do this, from hard-coding the path every time you need it, to hard-coding the path once at the top of your script and referring to it to dynamically compute it and set it once at the top of your script.

The third option is what most of the shelf CMSs use to work without a full knowledge of your file structure.

Why are you using a symbolically linked directory this way?

+2
source

I had a similar problem. You can do this using the $_SERVER['SCRIPT_FILENAME'] variable, which displays the requested file, so in your case it will be /mydocroot/include/somesubdir/include.inc.php , even if somesubdir is a symbolic link. To include a file that is one level lower instead of executing

 require_once "../settings.inc.php"; 

do the following:

 require_once dirname(dirname($_SERVER['SCRIPT_FILENAME'])).DIRECTORY_SEPARATOR."settings.inc.php" 

Variable documentation $_SERVER

+3
source

The solution is to create a basepath variable. The best way to do this is to include the following at the beginning of the script and then reference it

 $basepath = dirname(dirname($_SERVER['SCRIPT_FILENAME'])).DIRECTORY_SEPARATOR; 

Then you can reference the base path in your inclusion, required, etc. therefore

 include "../myscript.php"; 

Would

 include $basepath."myscript.php"; 

If you check the box again, you will have the following:

 include "../../myscript.php"; 

Would

 include $basepath."../myscript.php"; 

You must nest the dir_name functions twice, plus one more time for each additional folder for which you need to perform the return path. You MUST completely return to the folder where the symbolic link exists.

I consider this problem as a serious problem with PHP. I cannot come up with a single instance where it would be desirable to access reverse files relative to the actual file. In all situations, including shared hosting, it ONLY makes sense to go back along the connected path, and not to the target path.

+1
source

You can use is_link to check if the file is a symbolic link. If so, use readlink to get the absolute goal.

But over the ten years of php development, I never had a reason to use symbolic links. As Jason suggests, I always determined or deduced the absolute path once, and then used this throughout the application to make all file paths absolute.

0
source

All Articles