php_nub_qq
php_nub_qq

Reputation: 16065

Running php from cmd: relative paths issue

I am currently testing some code in cmd, and I'm experiencing some problems with relative paths.

pic

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

enter image description here

Upvotes: 2

Views: 2348

Answers (2)

hek2mgl
hek2mgl

Reputation: 158250

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.

Upvotes: 7

Aleksander Bavdaz
Aleksander Bavdaz

Reputation: 1346

As @hek2mgl points out, it has to do with the current working directory being wrong.

In your case the working directory is c:/xampp/php/ but it should be c:/xampp/htdocs/actualframework/public/. There's at least two solutions to fix this, the most obvious one being changing the working directory on the command line:

cd c:/xampp/htdocs/actualframework/public/
c:/xampp/php/php.exe index.php

Alternatively you can set the current working directory from your PHP script by adding the following into your index.php before you try to include/require anything:

chdir(realpath(dirname(__FILE__)));

Upvotes: 5

Related Questions