获得项目根目录

I keep getting confused when trying to include files that will have different paths in a local environment vs production.

For example, I have this in my usercontroller.php file:

require_once(__DIR__ . '/config.php');

On my local host, usercontroller.php is located in www/myproject/inc/ and config.php is in www/myproject/ (the project root directory)

This fails.

All I want is a way to define the projects root. i.e on localhost it's www/projectname and in productions it's / Since files are located inside the projectname directory on my localhost, it's causing issues on my production server.

What is the best way to simply define a base path and build my require_once from that?

i.e. require_once($basePath . 'inc/filename.php'

Most projects use a config.inc.php file located in a common place where these things can be defined.

config.inc.php

define('ROOT_FOLDER', '/');
define('APPLICATION_LINK', 'http://www.example.com/mysite');

script.php

require ('../config.inc.php');
echo '<a href="' . APPLICATION_LINK . '">Go home</a>';

Every project should contain a config.php file that holds this information.

config.php

define('ENVIRONMENT', 'PRODUCTION');
// define('ENVIRONMENT', 'TESTING');
// define('ENVIRONMENT', 'DEVELOPMENT');

switch (ENVIRONMENT) {
    case 'PRODUCTION':
        define('BASE_URL', 'http://www.mysite.com');
        define('BASE_PATH', '/');
        break;
    case 'TESTING':
        define('BASE_URL', 'http://test.mysite.com');
        define('BASE_PATH', '/test/');
        break;
    case 'DEVELOPMENT':
        define('BASE_URL', 'http://localhost/');
        define('BASE_PATH', '/www/myproject/');
        break;
}

Then maybe have a URL helper file.

url_helper.php

function site_url($relative) {
    return BASE_URL . $relative;
}

function redirect($uri = '', $method = 'location', $http_response_code = 302) {
    if ( ! preg_match('#^https?://#i', $uri)) {
        $uri = site_url($uri);
    }

    switch($method) {
        case 'refresh' : header("Refresh:0;url=".$uri);
                break;
        default : header("Location: ".$uri, TRUE, $http_response_code);
                break;
    }
    exit;
}

And a load helper.

load_helper.php

function load_file($uri) {
    require BASE_PATH . $uri;
}

function load_class($class) {
    if ( ! class_exists($class))
        load_file('class/' . $class);
}

These functions could be more robust to suit your needs. The advantage is you can have different configurations for Production/Development, various servers, or simply for specific environments. If you always use the site_url function to generate URLs around your site, you can easily change how your URLs are interpreted by making one change in a single file.

Maybe something like this could do the trick!

switch(dirname(__FILE__)) {
case '/www/myproject/inc/':
    //DEFINE SOMETHING
break;
case '/www/myproject/':
    //DEFINE SOMETHING
break;
}

As stated in the docs __DIR__ returns the directory of the file where it was used.

DIR - The directory of the file. If used inside an include, the directory of the included file is returned. This is equivalent to dirname(FILE). This directory name does not have a trailing slash unless it is the root directory. (Added in PHP 5.3.0.)

To include a file in an outer directory you'll have to use .. to "get out" of the inner directory.

require_once(__DIR__ . '../config.php');

On a side note, I would suggest you check out FIG's autoloading standards if you are using PHP's namespaces.

I know this answer is late, but you haven't accepted any yet, so I thought I'd throw in to the pot what I use for most of my applications.

First things first, from the file you call your config.php from, you will always need to use a relative reference for it, ie require_once '../config.php'; from your example. Granted, you can 'gather' the full path to the config file from PHP commands, but why would you do that when you know its one directory up, and within it, you can then define the base path for the entire project. For example, in your www/myproject/inc/usercontroller.php file, the top would look like:

<?php
require_once '../config.php';

And then, to auto-get the full basepath of the project for use in other includes or the like, in your config, you'd have something like:

<?php
$basepath = dirname(__FILE__);
define('BASEPATH', $basepath);
//Or all in one line:
define('BASEPATH', dirname(__FILE__));

From there, just use BASEPATH when you need the full path to the root of the project. ^^