Relative, absolute and bloody quantum paths in PHP! - php

I am building a web app (a forum), and it is to be integrated into various websites. The idea is that the folder location storing all the files is variable so that a webmin can put the forum wherever they like. I have, as usual, some PHP included files.
Say I have global.php and envars.php and want them included in app_root.php. The first two are stored in ./global/, relative to app_root.php. Now, when I use ./ I get a file not found error. If I use just global/ (no prepended slash), I get the same error.
I really need help on this :-(
The paths need to be relative to app_root.php and can't be absolute - the abs. path varies per installation.
Thanks for reading,
James

This problem is normally solved by creating a constant with an absolute path to the application.
Something like this in your app_root.php file
define('ROOT_PATH', dirname(__FILE__));
Then, to include other files just use something like
include ROOT_PATH . '/dir/file.php';

Related

Is it a good idea to use $_SERVER['DOCUMENT_ROOT'] in includes?

Is this, for example, a good idea?
require_once($_SERVER['DOCUMENT_ROOT'].'/include.php');
If you have two virtual hosts on the same server, one for live and one for development, with different Apache DocumentRoots, this would avoid having to include absolute paths when the source of the include is unknown, and may be in any directory.
(Note: file paths in the following section are relative to the web root. They would in fact be like /var/www/app/core/init.php, where /var/www/app is the web root)
For instance: I have an /core/init.php which is called using relative paths from places all over the website (/file.php, /dir/file.php or /dir/dir/file.php).
This init.php then includes several function pages, in the fund directory, a subdir of /core (as in /core/func/userfunctions.php).
So, in init.php, I can use the $_SERVER method, because it breaks if I use a relative path and try to call functions from a page like /dir/file.php.
I can't see any problem with it, but in general what could go wrong?
I've seen cases where $_SERVER['DOCUMENT_ROOT'] is not set or is not what you would expect (i.e. not set in CLI or old IIS, or invalid in certain CGI setups).
For that reason you can use dirname(__FILE__) to obtain the path of the script that line is called in. You can then reference relative paths from there e.g.
include dirname(__FILE__) . '/../../other/file.php';
I go with the above method when the directory structure of the files is known and is not subject to change.
If DOCUMENT_ROOT is not available, the following is a suitable replacement:
substr($_SERVER['SCRIPT_FILENAME'], 0, -strlen($_SERVER['SCRIPT_NAME']));
You don't need to do this. PHP looks for the included file in the document root by default.
You can use set_include_path($new_include_path) to change this behaviour, or edit include_path in the php config file.
Also, from http://php.net/manual/en/reserved.variables.server.php:
'DOCUMENT_ROOT'
The document root directory under which the current script is executing, as defined in the server's configuration file.
For example, if you use URL rewriting, you will be very happy when you find out that the includes in your /there/are/so/many/paths/in/the/url/of/this/ page are still working!

php - header file - relative paths problem

I have a web application in php. I have a header.php file where I have the opening html tag, meta data, css,js file includes.
I have multiple folders in this application. I have given relative paths to the css,js files in the header.php. The problem I am facing is, when I include this header.php file in some other file say, ./test-folder/my-file.php, the relative paths break.
so to solve this i have given absolute paths where ever needed. But I have to change these paths every time I upload on to server. Can this be done in any other way?
Thanks in advance
Anji
Do not use static value for path instead define a constant for document root and use that constant
define('ROOT_PATH',$_SERVER['DOCUMENT_ROOT']);
While including files you can use this constant.
include ROOT_PATH.'/some_dir/file.php';
You have bad architecture in your application. Try to search info about MVC.
This answer may be useful: https://stackoverflow.com/questions/5721353/what-is-good-neat-architecture-in-programming/5793753#5793753
So:
change architicture,
use autoload
Relative paths are relative to the current working directory (cwd). If you just include another file that cwd does not change.
If you want to have paths that are (somewhat) relative to the current script file path you can use e.g.
require dirname(__FILE__).'/some_dir/file.php';
or as of php 5.3
require __DIR__.'/some_dir/file.php';
see also: http://docs.php.net/language.constants.predefined
If I understood your question right, you just would like to know the root folder your application without the need to hardcode it.
The easier way is to define a constant as Shakti has answered.
However, you could actually have a file with a unique name such as "foobar" in the root folder, then walk up the tree from current directory until you find foobar.

use absolute or relative path?

in my config.php where i have all constants i set the PATH to a absolute path.
but this means that when i move my application folder i have to change this path.
i wondered if its better to set a relative path, in that way whenever i move my application between production and development folder, i dont have to change it.
how do you guys do when you move between folders?
The best way I've found is to do the following:
define("PATH", realpath(dirname(__FILE__)));
That gives you the directory of the current file. If you do this in your settings/bootstrap/init file, you'll have it available to your application, and it will work for any file system.
__FILE__ is your friend.
define('BASE_PATH', dirname(realpath(__FILE__)));
This will make your scripts more portable.
Include a file like this
include BASE_PATH . 'includes/header.php';
IMO, absolute paths are bad news. Even if you don't plan to move, your hosting provider could move you, like DreamHost recently did to me. I was fine....
But there are 14 references to "path" on their wiki:
http://wiki.dreamhost.com/Server_Moves
I do three things to solve this:
The first is to use paths relative to the current file and include things using dirname(__FILE__).
The second is to use a loader include that all the pages load. This file has one responsibility: to find the include directory, usually via a relative call. So long as this relative relationship stays, it doesn't need changing.
I also like to support custom settings that belong to the installation rather than the codebase. This is done by an include mechanism and overrides a few settings that will be specific for the server the code is on.

php include path changing based on file

I'm brand new to php and I'm trying to work with some includes in my site and can't quite figure out how to make them all work correctly.
My site structure is as follows
/ROOT/
Config.php
Index.php
/ADMINISTRATION/
Index.php
mustInclude.php
/USERS/
Index.php
If "mustInclude.php" includes "Config.php" and Index.php includes "mustInclude.php" everything works fine, but as soon as I try to include "mustInclude.php" into /USERS/Index.php it breaks because "mustInclude.php" is using a path like include '../config.php'; and that isn't the same relative path for /USERS/Index.php as for /ADMINISTRATION/Index.php
I'm not really sure what to do here.
This is on my local machine for now. Using $_SERVER['DOCUMENT_ROOT'] gives me errors because it outputs my file structure (/Users/James/Sites) rather than my web structure (http://localhost/mysite)
Help?
I suggest defining some kind of "global base path" and deducing the other paths from there. Like,
define('BASE_PATH', '/home/me/');
...
include(BASE_PATH . 'Config.php');
include(BASE_PATH . 'subdirectory/other.php');
and so on. This kind of (semi)absolute paths are less fragile than relative paths containing lots of ../s. (Not to say that there's anything fundamentally wrong with relative paths, but they're harder to get just right and tend to break more easily. If /a includes b/c and b/c includes ../d/e, is that relative to /b/ or relative to /, or does it depend on whether we started from /a vs. called b/c directly? I don't even know. Better just use the absolute paths, they're easy and unambiguous :-).
IMO the best way to include files from anywhere in your application directory structure is to add the root folder of your app to your PHP include path:
<?php
set_include_path(get_include_path().PATH_SEPARATOR."/Users/James/Sites/app_name");
Then, just include files using their paths relative to the application root folder, for example:
<?php
require_once('ADMINISTRATION/USERS/Index.php');
Instead of using '../config.php' try using
dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'config.php'
This way you will always know that one level above is one level above from the current file.
you can use __FILE__

How do I set an absolute include path in PHP?

In HTML, I can find a file starting from the web server's root folder by beginning the filepath with "/". Like:
/images/some_image.jpg
I can put that path in any file in any subdirectory, and it will point to the right image.
With PHP, I tried something similar:
include("/includes/header.php");
...but that doesn't work.
I think that that this page is saying that I can set include_path once and after that, it will be assumed. But I don't quite get the syntax. Both examples start with a period, and it says:
Using a . in the include path allows for relative includes as it means the current directory.
Relative includes are exactly what I don't want.
How do I make sure that all my includes point to the root/includes folder? (Bonus: what if I want to place that folder outside the public directory?)
Clarification
My development files are currently being served by XAMPP/Apache. Does that affect the absolute path? (I'm not sure yet what the production server will be.)
Update
I don't know what my problem was here. The include_path thing I referenced above was exactly what I was looking for, and the syntax isn't really confusing. I just tried it and it works great.
One thing that occurs to me is that some people may have thought that "/some/path" was an "absolute path" because they assumed the OS was Linux. This server is Windows, so an absolute path would have to start with the drive name.
Anyway, problem solved! :)
What I do is put a config.php file in my root directory. This file is included by all PHP files in my project. In that config.php file, I then do the following;
define( 'ROOT_DIR', dirname(__FILE__) );
Then in all files, I know what the root of my project is and can do stuff like this
require_once( ROOT_DIR.'/include/functions.php' );
Sorry, no bonus points for getting outside of the public directory ;) This also has the unfortunate side affect that you still need a relative path for finding config.php, but it makes the rest of your includes much easier.
One strategy
I don't know if this is the best way, but it has worked for me.
$root = $_SERVER['DOCUMENT_ROOT'];
include($root."/path/to/file.php");
The include_path setting works like $PATH in unix (there is a similar setting in Windows too).It contains multiple directory names, seperated by colons (:). When you include or require a file, these directories are searched in order, until a match is found or all directories are searched.
So, to make sure that your application always includes from your path if the file exists there, simply put your include dir first in the list of directories.
ini_set("include_path", "/your_include_path:".ini_get("include_path"));
This way, your include directory is searched first, and then the original search path (by default the current directory, and then PEAR). If you have no problem modifying include_path, then this is the solution for you.
There is nothing in include/require that prohibits you from using absolute an path.
so your example
include('/includes/header.php');
should work just fine. Assuming the path and file are corect and have the correct permissions set.
(and thereby allow you to include whatever file you like, in- or outside your document root)
This behaviour is however considered to be a possible security risk. Therefore, the system administrator can set the open_basedir directive.
This directive configures where you can include/require your files from and it might just be your problem.
Some control panels (plesk for example) set this directive to be the same as the document root by default.
as for the '.' syntax:
/home/username/public_html <- absolute path
public_html <- relative path
./public_html <- same as the path above
../username/public_html <- another relative path
However, I usually use a slightly different option:
require_once(__DIR__ . '/Factories/ViewFactory.php');
With this edition, you specify an absolute path, relative to the file that contains the require_once() statement.
Another option is to create a file in the $_SERVER['DOCUMENT_ROOT'] directory with the definition of your absolute path.
For example, if your $_SERVER['DOCUMENT_ROOT'] directory is
C:\wamp\www\
create a file (i.e. my_paths.php) containing this
<?php if(!defined('MY_ABS_PATH')) define('MY_ABS_PATH',$_SERVER['DOCUMENT_ROOT'].'MyProyect/')
Now you only need to include in every file inside your MyProyect folder this file (my_paths.php), so you can user MY_ABS_PATH as an absolute path for MyProject.
Not directly answering your question but something to remember:
When using includes with allow_url_include on in your ini beware that, when accessing sessions from included files, if from a script you include one file using an absolute file reference and then include a second file from on your local server using a url file reference that they have different variable scope and the same session will not be seen from both included files. The original session won't be seen from the url included file.
from: http://us2.php.net/manual/en/function.include.php#84052
hey all...i had a similar problem with my cms system.
i needed a hard path for some security aspects.
think the best way is like rob wrote. for quick an dirty coding
think this works also..:-)
<?php
$path = getcwd();
$myfile = "/test.inc.php";
/*
getcwd () points to:
/usr/srv/apache/htdocs/myworkingdir (as example)
echo ($path.$myfile);
would return...
/usr/srv/apache/htdocs/myworkingdir/test.inc.php
access outside your working directory is not allowed.
*/
includ_once ($path.$myfile);
//some code
?>
nice day
strtok
I follow Wordpress's example on this one. I go and define a root path, normally the document root, and then go define a bunch of other path's along with that (one for each of my class dirs. IE: database, users, html, etc). Often I will define the root path manually instead of relying on a server variable.
Example
if($_SERVER['SERVERNAME'] == "localhost")
{
define("ABS_PATH", "/path/to/upper/most/directory"); // Manual
}
else
{
define("ABS_PATH, dirname(__FILE__));
// This defines the path as the directory of the containing file, normally a config.php
}
// define other paths...
include(ABS_PATH."/mystuff.php");
Thanks - this is one of 2 links that com up if you google for php apache windows absolute path.
As a newbie to intermed PHP developer I didnt understand why absolute paths on apache windopws systems would be c:\xampp\htdocs (apache document root - XAMPP default) instead of /
thus if in http//localhost/myapp/subfolder1/subfolder2/myfile.php I wanted to include a file from http//localhost/myapp
I would need to specify it as:
include("c:\xampp\htdocs\myapp\includeme.php")
or
include("../../includeme.php")
AND NOT
include("/myapp/includeme.php")
I've come up with a single line of code to set at top of my every php script as to compensate:
<?php if(!$root) for($i=count(explode("/",$_SERVER["PHP_SELF"]));$i>2;$i--) $root .= "../"; ?>
By this building $root to bee "../" steps up in hierarchy from wherever the file is placed.
Whenever I want to include with an absolut path the line will be:
<?php include($root."some/include/directory/file.php"); ?>
I don't really like it, seems as an awkward way to solve it, but it seem to work whatever system php runs on and wherever the file is placed, making it system independent.
To reach files outside the web directory add some more ../ after $root, e.g. $root."../external/file.txt".

Categories