I'm writing a Router class for a library of mine. This class will keep the locations of some paths, but I'm wondering if I should use 'intelligent' absolute paths, relative paths or both (for this case) will be the same thing.
Obs.1: When I wrote 'intelligent' absolute path is because this absolute path will work even if the admin move the library to another location.
Obs.2: Stack has other questions about this topic, but looks like they aren't about what I'm looking for, so I did the question.
First solution:
MyVendor/src/class/MyVendor/MyNamespace/Router.php
using 'intelligent' absolute path
namespace MyVendor\MyNamespace;
class Router
{
private $root;
private $cache;
public function __construct()
{
$this->setRootPath();
$this->cache = "{$this->root}var/cache/";
}
public function setRootPath()
{
$currentDir = __DIR__;
$exploded = explode("/", $currentDir);
array_pop($exploded); // Removing MyNamespace
array_pop($exploded); // Removing MyVendor
array_pop($exploded); // Removing class
array_pop($exploded); // Removing src
$this->root = implode("/", $exploded)."/";
}
}
Second solution:
MyVendor/src/class/MyVendor/MyNamespace/Router.php
using relative path
namespace MyVendor\MyNamespace;
class Router
{
private $root;
private $cache;
public function __construct()
{
$this->setRootPath();
$this->cache = "{$this->root}var/cache/";
}
public function setRootPath()
{
$this->root = __DIR__."/../../../../";
// ..(pointing to MyVendor)/..(pointing to class)/..(pointing to src)/..(pointing to the root, MyVendor)
}
}
Obs.3: See the first solution will use links like:
root => `/var/www/myproject/vendor/MyVendor/`
cache => `/var/www/myproject/vendor/MyVendor/var/cache`
and the second one will use links like:
root => `/var/www/myproject/vendor/MyVendor/src/class/MyVendor/MyNamespace/../../../../`
cache => `/var/www/myproject/vendor/MyVendor/src/class/MyVendor/MyNamespace/../../../../var/cache/`
Obs.4: the initial processing (using array_pop) is irrelevant to me.
So, what solution should I use and why? Is there another better way to do this (if yes, please write a Router class alternative)?
Why not simply ask for it?
namespace MyVendor\MyNamespace;
class Router
{
private $root;
private $cache;
public function __construct($rootPath)
{
$this->root = $rootPath;
$this->cache = "{$this->root}var/cache/";
}
}
Injecting the root path allow the clients of your library to put it (physically) anywhere they want. In your exemple, you suppose the root path is 4 dir up; What if it is not the case?
First, I'd definitely use realpath()
on your relative path work if you decide to use it (simplifies it for the developers and makes it easier to predict).
Second, I'd dispense with your array_pop() technique, that will fall apart real fast if you decide to reorganize things.
I'd opt for a preg_replace('#^'.$FS_ROOT.'#', __FILE__);
type approach to determine what's being called.
I think you should look at a reverse in your flow of information and pass in the 'base' of your project and then determine everything from there. This would save you a great headache when you move it around or have multiple copies of that code running for development.