ChaseMoskal
ChaseMoskal

Reputation: 7651

PHP Get Relative Path from Parent to Included File

I have a directory structure like this:

www/
  index.php
  my-library/
    my-library.php
    assets/
      my-library.css
      images/
        loading.gif

I need my-library.php to inject stylesheets into index.php. To do so, I need to get the relative path from index.php to my-library/ -- which in this particular case, would simply be "my-library".

From within my-library.php, is it possible for me to acquire this relative path?

Or must index.php supply it, with something like the following?

<?php
require "my-library/my-library.php";
$mlib->linkroot='my-library';
?>

To clarify, below I have included a more detailed representation of what I'm trying to do:

index.php:

<?php require "my-library/my-library.php"; ?>
<!doctype html>
<head>
  <title>Testing My Library</title>
  <?php $mlib->injectAssets(); ?>
</head>
<body>..</body>

my-library.php:

<?php
class MyLibrary(){
  public $rootpath;
  public $linkroot;
  function __construct(){
    $this->rootpath= __DIR__; // absolute path to my library's root directory (for serverside use)
    $this->linkroot = "???"; // relative path to my library's root from index.php (for clientside use, like linking in stylesheets)
  }
  function injectAssets(){
    $csslink = $this->linkroot.'/assets/my-library.css';
    echo '<link href="'.$csslink.'" rel="stylesheet" />';
  }
}
$mlib = new MyLibrary();
?>

The line I'm interested in figuring out, would be $this->linkroot = "???";.

I'm practically trying to acquire the string that was used to include/require the current script.

Upvotes: 1

Views: 741

Answers (3)

CAtoOH
CAtoOH

Reputation: 81

Have you tried doing a relative link from the root? If not, you might try something like this, if I understand your folder structure.

<link href="/my-library/assets/my-library.css" rel="stylesheet" type="text/css" />

Links like this in any page within your site will pull the same stylesheet, up or down the site structure.

Upvotes: 0

ChaseMoskal
ChaseMoskal

Reputation: 7651

I got it! I only had to build a Rube Goldberg Machine to do it!

Thanks PHP.

$linkroot = ascertainLinkroot();

function ascertainLinkroot(){
  return makeRelativePath(
    getTopScriptPath(),
    __DIR__
  );
}

function getTopScriptPath(){
  $backtrace = debug_backtrace(
    defined( "DEBUG_BACKTRACE_IGNORE_ARGS")
      ?DEBUG_BACKTRACE_IGNORE_ARGS
      :FALSE );
  $top_frame = array_pop($backtrace);
  $top_script_path = $top_frame['file'];
  return $top_script_path;
}

function makeRelativePath($from,$to){
  // Compatibility
  $from = is_dir($from) ?rtrim($from,'\/').'/' :$from;
  $to   = is_dir($to)   ?rtrim($to,'\/').'/'   :$to;
  $from = str_replace('\\','/',$from);
  $to   = str_replace('\\','/',$to);
  //----------------------------
  $from = explode('/',$from);
  $to   = explode('/',$to);
  $path = $to;
  foreach($from as $depth => $dir) {
    if ($dir === $to[$depth]) { // find first non-matching dir
      array_shift($path); // ignore it
    } else {
      $remaining = count($from)-$depth; // get number of remaining dirs to $from
      if ($remaining>1){
        // add traversals up to first matching dir
        $padLength = -(count($path)+$remaining-1);
        $path = array_pad($path, $padLength, '..');
        break;
      } else {
        $path[0] = './'.$path[0];
      }
    }
  }
  return rtrim(implode('/', $path),'\/');
}

So, basically, I use the makeRelativePath function to calculate a relative path from the top script's absolute path to the current script's absolute directory path (__DIR__).

I realized that I'm actually looking for the relative path to the library from the top script, not just the parent script -- because the top script is the one where clientside assets will need to be referenced in relation to.

Naturally, PHP doesn't just give you the top script's absolute path. On some environments, the top script's path can be available as a $_SERVER variable, however environment independence is important for me, so I had to find a way.

getTopScriptPath was my solution, as it uses debug_backtrace to find it (creepy, I know), but it is the only environment-independent way to fetch it (to my knowledge).

Still hoping for a more elegant solution, but am satisfied that this one works.

Upvotes: 2

mister martin
mister martin

Reputation: 6252

I believe this is what you're looking for:

$this->linkroot = basename(pathinfo($_SERVER['REQUEST_URI'], PATHINFO_DIRNAME));

You can remove basename() to get the full path. Basically, you can run the following code:

echo '<pre>';
var_dump($_SERVER);
echo '</pre>';

If the path you're looking for isn't there in some shape or form, then it simply isn't available and you will have no other choice but to hard code it, or at least hard code part of it.

Upvotes: 0

Related Questions