tags:

views:

74

answers:

4

I am about to create a collection of classes in php which are interrelated. Now I would like to include files using their absolute path, ie

If I were in

'/com/mysite/licences/Generator.class.php'

I would like to include files like this:

include '/com/mysite/lib/Utils.class.php'

I don't want to include like this, I think it is confusing and ugly

include '../licenses/Utils.class.php'

This works ok, unless 'com' is not in the root of public_html. I assume I will need some sort of prefix to append to each file LIBRARY_ROOT that hold the location of 'com' in the current filesystem. So it might look like this

include LIBRARY_ROOT.'com/mysite/lib/Utils.class.php'

What is the best way to do this?

-----------------MY SOLUTION----------------

UPDATE :

It looks like this solution didn't work either because the set_include_path('/'); appears to reset at the closing php tag ?> not the one in the including file.


This is what I did

Created a file called like the following in the root of the filesytem

com.mysite.setup.inc.php

the long name is in the Java format for package names, it is like this to help prevent naming conflicts. If I called it setup.php it is possible that another file will also be called setup.php in the root folder.

com.mysite.setup.inc.php contains the following:

<?php
/**
 * Setup file for each class
 */

//Path
set_include_path('/');

//Other common setup

?>

This will always be in the root folder so all classes can call it like this:

include '/com.mysite.setup.inc.php';

If the library gets moved all you have to do is update com.mysite.setup.inc.php to reflect the changes.

What we get is a clean naming convention with no need to append ugly PREFIXES to every single include. We can now include like this in any class file.

include '/com.mysite.setup.inc.php';
include 'com/mysite/lib/Utils.class.php';
include 'com/mysite/lib/text_utilities/Text.class.php';
include 'com/mysite/encryption/Cipher.class.php';

class MyClass {.......
A: 

Just

define ('LIBROOT', $_SERVER['DOCUMENT_ROOT'].'/com/mysite/');

And include like

include LIBROOT. 'lib/Utils.class.php';

$_SERVER['DOCUMENT_ROOT'] will work in 99% cases.

Deniss Kozlovs
If I use this solution I will have to hard code the path /com into every class, what if at some stage I move the library?
jax
You're supposed to define that in a common file used in your include chain
rmontagud
A: 

You could alternatively consider setting the include_path to your library base directory, and just include("lib/utils.class.php").

mario
If I added the set_include_path directive in a file at the root of 'com' setIncludePath.php. I would then simply include this at the top of all my classes before including anything else, am I correct in my thinking here?
jax
Actually I just realised that even if I set the include path, there is still no way of knowing what the include path will be. It can change manually but I only want to change it once. not in every file. So even If I include the file I will have 'relatively' (../../../../../) go down to com and include the file. Each file will need a diferent relative path depending on where it is.
jax
Your updated solution looks abour right. And this is exactly what PHPs include_path is meant for. Btw, have you read about __autoload? This magic method can load individual class scripts whenever a class gets instantiated. Might spare you all the manual include calls (except mysite.setup.inc.php) if each of your class files corresponds to one actual class.
mario
A: 

Basing your path on DOCUMENT_ROOT can end up a little messy if your scripts are outside the document root (which ideally, they will be). You may also need to watch out for cross-platform compatibility when it comes to directory separators. Windows is usually not too fussy and will accept backslashes and forward slashes, but that tends not to be the case on other operating systems.

You could derive your library root path from the filename of a script. Choose a script with a path that, relative to your library, will remain constant. I usually have a script (called constants.php) which I call right at the start of my application. It defines a series of constants that are used in the application.

From there, I use SCRIPT_FILENAME to derive a path to my library files. This method means that you can move your scripts around on the filesystem, or to another filesystem, and they will still resolve the correct paths. I've included a quick and dirty function which breaks one or more paths down, then recombines them using the correct operating system directory separator:

In constants.php:

define(
    'MY_LIB',
    combine_path(
        dirname($_SERVER['SCRIPT_FILENAME']),
        'lib/my_lib'
    )
);

define(
    'THIRD_PARTY_LIB',
    combine_path(
        dirname($_SERVER['SCRIPT_FILENAME']),
        'lib/third_party_lib'
    )
);

function combine_path() {
    // Get an array of function arguments.
    $args = func_get_args();

    // Prepare an array to hold the list of path nodes.
    $path = array();

    // Process each argument.
    foreach ($args as $arg) {
        // Split the path at backslash or forward slash separators.
        $nodes = preg_split('/[\\/\\\]/', $arg);

        // Push each node onto the end of the path array.
        foreach ($nodes as $node) {
            $path[] = $node;
        }
    }

    // Join the path nodes with the system's directory separator.
    return implode(DIRECTORY_SEPARATOR, $path);
}
Mike
I just think I solved this. What do you think of the solution above? (updated the question)
jax
I think your solution would work, but it still requires manually editing the path if things change. It also becomes more difficult if your application is deployed to a shared hosting environment where you do not have access to the root directory. If you define a path relative to a known location (the location of a running script), then you avoid this problem. You can, of course, then add this path to the include path. You may also want to check out autoloading of classes (http://php.net/manual/en/language.oop5.autoload.php), as this can reduce the number of includes you need to make.
Mike
I will have a look, thanks
jax
It turns out my solution did not work
jax
A: 

you should use the autoload function, and in your autoload keep going up a dir in a loop till you find you lib dir, then append the path onto the classfile you are looking for.

something like

<?php
function __autoload( $className ){
// where all your classes are. 
//you can add logic for namespaces fairly easily here as well
$classDir = "lib"; 
// the path to your library we wil modify this in the loop
$pathPrefix = '';

while( !is_dir( $pathPrefix . $classDir )){
    $pathPrefix .= '../';
}

if( file_exists( $pathPrefix . $classDir . DIRECTORY_SEPARATOR . $className . 'php' )){
    include( $pathPrefix . $classDir . DIRECTORY_SEPARATOR . $className . 'php' );
}else{
    throw new Exception( $className . ' could not be found by autoload' );
}

}

David Morrow