Running php from cmd: relative paths issue
cmd, php, windows
Solution
Basics:
When called from HTTP the working directory of `index.php` is `C:\xampp\htdocs\actualframework\public\` when called from command line (in your example) it is `C:\xampp\php`. So the script tries to include `C:\xampp\Framework/class/routers/System.php` which isn't there.
You need to utilize the `__DIR__` constant in order to make the require command working independently from where `index.php` was called:
require(__DIR__ . "/../Framework/class/routers/System.php");
`__DIR__` points to the directory where the source file is located which is using the `__DIR__` constant, in your example: `C:\xampp\htdocs\actualframework\public\`
Using `include_path`
Another good idea is to utilize the `include_path` directive in order to make the real location of a library file transparent to the application. This will give you more freedom when you once change the directory layout. `include_path` is a configuration value that can be set in `php.ini` or in scripts and contains a list od directories where php should look if you pass relative paths to `require` or `include` as well as some functions like `file_get_contents()`, `fopen()`, ...
Configure the include path on top of your `index.php` (or in a separate `bootstrap.php` which gets included):
ini_set('include_path', implode(PATH_SEPARATOR, array(
__DIR__ . '/../Framework/class',
__DIR__ . '/../Framework/interface',
// add the existing value at the end
ini_get('include_path')
)));
Now you can use paths like this to require classes:
require_once 'System.php';
require_once 'routers/Foo.php';
Autoloading
Since PHP5 there is a feature called `autoloading` which eases the including of classes. Autoloading basically provides the ability to define a hook function which gets called every time a class is accessed which has not been defined before. Imagine you have the following files:
lib/Person.php
<?php
class Person {
... some code
}
index.php
<?php
$hek2mgl = new Person();
Normally this code will trigger an error because `Person` is accessed without including `lib/Person.php` before. This is the point where autoloading can be used. Lets see how a simple autoload method can look like in this (simple example):
function autoload($classname) {
$path = __DIR__ . "/lib/$classname.php";
if(file_exists($path)) {
require_once $path;
}
}
You need to reqister the autoloader using `spl_autoload_register()`. `index.php` can look like this:
<?php
// define simple autoloader for project
function autoload($classname) {
$path = __DIR__ . "/lib/$classname.php";
if(file_exists($path)) {
require_once $path;
}
}
// register autoloader
spl_autoload_register('autoload');
// will work now
$hek2mgl = new Person();
If you ask me, autoloading is one of the coolest things in PHP5. You can refine the autoload method in order to work with the `include_path` directive. Doing so it gets easy to work with a couple of libraries without taking care about where they are physically stored in filesystem. You may give my `Jm_Autloader` a try, the code is on github and you can install it using PEAR or composer.
Problem
I am currently testing some code in cmd, and I'm experiencing some problems with relative paths. It is clearly visible that the path is set correctly, furthermore it works as expected under http protocol. I assume there's something that's blocking relative paths in cmd, because if I replace that with an absolute path the file gets included. This however is not efficient as filesystems may change and the use of relative paths is a must. I'm really bad with OS stuff so I guess I shouldn't be making any more assumptions. Thanks! EDIT: Mind = Blown