Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP include file strategy needed

Tags:

php

I'm in the process of setting up a php project, but am not very familiar with how to properly use php's include/require commands. My layout currently looks like this:

/public   --apache points into this directory  
/public/index.php  
/public/blah/page.php  
/utils/util1.php       -- useful classes/code are stored in other directories out here  
/dbaccess/db1.php  

dbaccess/db1.php  



require '../utils/util1.php

public/index.php

require '../dbaccess/db1.php'

public/blah/page.php

require '../../dbaccess/db1.php'

The problem is this from the php 'include' documentation:

If filename begins with ./ or ../, it is looked only in the current working directory

So public/blah/page.php fails because it includes dbaccess/db1.php which blows up when it tries to include util1.php. It fails because it's relative path is from the original script in public/blah/, not from dbaccess/

This seems pretty stupid -- db1.php has to just know where it's being included from which isn't going to work.

I've seen strategies like this:

require_once dirname(__FILE__) . '/../utils/util1.php');

That apparently works since now the path is an absolute path, but just seems really bizarre to me.

Is that normal? Should I continue down that path or am I missing something obvious here?

like image 496
Clyde Avatar asked Dec 04 '08 00:12

Clyde


3 Answers

Usually, the standard conventions are thus: like @grepsedawk said, you'll want to define a constant that contains the root of your project folder and if you can the root of your includes folder:

define('APP_ROOT', dirname(__FILE__));
define('INCLUDE_ROOT', APP_ROOT . "/includes");

Note: the constant name needs to be a string!

Also, you'll notice I'm using dirname(__FILE__);. If you place your constants definition file in a subdirectory, you can do a dirname(dirname(__FILE__));, which is the equivalent of a ../.

Now some other caveats. While PATH_SEPARATOR is a cool constant, it is not needed. Windows accepts / or \ in path names, and since Linux only users / as a path separator, go ahead and always use a / instead of mucking up your code with repeated references to PATH_SEPARATOR.

Now that you have your root constants defined, what you'll do when you need a configuration file included is a simple:

include INCLUDE_ROOT . '/path/to/some/file.php';

You'll probably want your constant definitions (the define(...)'s above) in a bootstrap script in your root directory:

www_root/
  index.php
  bootstrap.php

The bootstrap will contain the defines (or an include of the constants file), as well as an include of any files that will be required by EVERY page.

And finally the last standard convention you may not use, but if you start doing object oriented programming, the most common method (the PEAR standard) is to name your classes by using an _ to separate namespaces:

class GlobalNamespace_Namespace_Class
//...

And then organizing your file structure mapping name spaces to subdirectories (literally replacing all _'s with /'s):

include_dir/
  GlobalNamespace/
      Namespace/
          Class.php

And using __autoload() functions to load your classes, but that's another question.

like image 100
dcousineau Avatar answered Oct 05 '22 10:10

dcousineau


Have a configuration script that sets the "INSTALL ROOT" of your project and then use absolute paths. Relative path with multiple includes is a headache in php.

DEFINE("INSTALL_ROOT", "/path/to/www/project")

require_once(INSTALL_ROOT . '/util1.php')

like image 32
grepsedawk Avatar answered Oct 05 '22 12:10

grepsedawk


in my config / setup file, i do something like

define('MYAPP_BASEDIR',realpath('.'));

then i reference everything relative to that.

... if your include directory relates specifically to class files and you are able to name them so that the include file name could be derived from the class, you might like to look into spl_autoload_register().

this latter part isn't a direct answer to your question, but it's very handy if you're doing includes for each class you use.

like image 20
Chris Burgess Avatar answered Oct 05 '22 10:10

Chris Burgess