I've taken over a site that caters for client access. They all access there own folder, and in the folder the files have an include with a relative path as below.
/core - contains all the actual files
/client/file.php -
<? include "../core/file.php"; ?>
but with the growing number of clients I want to go a level deeper and separate them better...
/uk/client/file.php -
<? include "../../core/file.php"; ?>
This is fine but when the files are included, they too have there own relative includes and this is where it breaks.
There are so many files I can't easily go through them to change all the include paths so I would like to maybe do a rewrite to fake the path?
I've tried this...
RewriteRule ^uk/$ /
But that doesn't work.
Any help would be greatly appreciated
This sound like a work for __DIR__, you can check documentation here
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.)
Otherwise you can still switch all your relative paths to absolute path and avoid any problem if some file are included in others.
As side note i would reccomend to not use php short tag <?...?>, I'd rather use long tags <?php....?>
Related
I am really confused about PHP and the path system.
I have this structure:
- Includes
- Login
- View
* Secure
These are all directories on my site. Now, if i place files in the "View" folder, i can access files in my Includes folder with:
"../Includes/file.php"
If i want to include the same file from the Secure directory, i would do:
"../../Includes/file.php"
This is all fine, but here is where it gets tricky for me.
If the file i try to import (the file.php in the Includes directory) ALSO includes a file, it will throw everything off. Say that file will include a file in "Login", it would have to be ONE of these 2 includes, all depending on if the code that includes it is in the Secure or View directory:
"../Login/file.php" -> if it was included from the View directory
"../../Login/file.php" -> if it was included from the Secure directory.
Obviously this problem only gets worse and worse. Maybe what i am after, is a way to have the path be relative to the FILE itself, and NOT the including code?
On another note, i guess what i am really after is how to handle all this include "hell" in PHP? I feel that i bind my structure tightly together and that i can't change much without everything breaking. So any advise on how to handle this is greatly appreciated.
There are two types of paths: relative, and absolute. Absolute paths start with a /.. (or C:/.. or however that works on Windows) and always unequivocally point at one specific file.
Relative paths (not starting with /) are relative to the include_path variable. That's a variable that contains a bunch of folders, where PHP will look for your relative path. That include_path also includes ., the current directory. The "current" directory depends on which file was the "first" to be executed. So it varies depending on which file starts to include others.
You can set your include_path to some specific, unchanging directory, so you always have a fixed path to include to relatively.
Better: construct absolute paths:
include __DIR__ . '/../Login/file.php';
This is always relative to the directory the file is in.
I'm having a spot of bother with php includes. I have the following file structure
htdocs
index.php
login.php
php_includes
db_conx.php
check_user_status.php
within the db_conx.php file i've creates a variable $number = 10; for testing.
The db_conx file is included in the check_user_status.php file with the following code:
include_once("db_conx.php");
and that is working fine - i.e. i can echo $number and get 10.
However, I'm including the check_user_status.php file at the top of login.php with this code:
include_once("php_includes/db_conx.php");
and on this page I'm unable to echo out $number on this page (check_user_status.php).
I'm going to need this script included in many pages (since it checks whether the user is logged in or not). Am I doing something strange with the paths?
For relative paths you need to do this.
include_once("../php_includes/db_conx.php");
To break this down.
Your Current working directory is initially going to be htdocs/ if your hit that file in your browser.
the .. back you up one directory level (so the directory that contains both htdocs and php_includes)
then you want to follow down php_includes to get to db_conx.php.
This will become a problem when you do a file in a subdirectory. Assuming you and a page2.php to a htdocs/subpages/
Now if we follow those same steps we are not going to arrive at the same location.
A better approach is to get the path relative to an absolute location. I like using the document root (htdocs in your case), so:
include($_SERVER["DOCUMENT_ROOT"]."/../php_includes/db_conx.php");
will refer to the same place on the file system regardless of where it is used.
I think you can use __DIR__ magic constant
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.)
This will help you with nested included files, infact the file path will be always set automatically and you don't have to deal with absolute paths.
If your file structure is correct, assuming that php_includes is NOT a directory within htdocs, you would need to do:
include_once("../php_includes/db_conx.php");
I have many PHP files in
/
/client/
/user/
/config/
etc...
I want all my files to include /user/codestart.php. (Lots of functions etc)
Therefore:
All files in / have include("./user/codestart.php");
All files in /user/ have include("codestart.php");
All files in /client/ have include("../user/codestart.php");
The problem is that /user/codestart.php has include("../config/config.php"); (The MySQL ID and password)
When a file in / runs, such as /index.php, it includes ./user/codestart.php.
Then /user/codestart.php includes ../config/config.php, but it cannot see it, because it thinks it is calling it from /, instead of from /user/.
If I change
include("../config/config.php") to be
include("./config/config.php")
that fixes it for / files, but breaks it for/user/ and/client/ files.
Bottom line is that when one PHP file includes another file, PHP thinks it is operating from the location of the original file, not the calling file.
I need to use relative paths, not absolute paths. Absolute paths will not work in my situation.
Is there any way to solve this?
One way to deal with this is this:
Have a central configuration file (e.g. /myproject/config/bootstrap.php
In that configuration file, define a global root for your application. E.g.
define("APP_ROOT", realpath(dirname(__FILE__)."/.."));
Include that configuration file in every PHP file. E.g.
include("../config/bootstrap.php");
Whenever you reference some other file, use
include APP_ROOT."/includes/somefile.php";
Voilá - you have a fixed point in space (APP_ROOT) and can reference everything relative to that, no matter which directory you are in.
If you want to do it this way I suggest you make a seperate file for all your includes which is in a fixed dir, the root for example.
Then you reliably include all the files from there using
include __DIR__.'path/relative/from/includefile.php'
If your php verion is lower than 5.3 you should use dirname(__FILE__) instead of __DIR__ as mentioned by RiaD
You might like this php.net page
You can use relative paths in conjuntion with dirname(__FILE__)
So in your codestart file write:
require_once dirname(__FILE__).'/../config/config.php';
You can set the path that PHP uses to look for files, so that it contains all your folders. In index.php:
$folders = implode(PATH_SEPARATOR, array('user', 'config'));
set_include_path(get_include_path().PATH_SEPARATOR.$folders);
Then you can just do:
include("codestart.php");
and:
include("config.php");
This will work for index.php and all files that index.php includes.
use absolute paths. to get path to your root directory use $_SERVER['DOCUMENT_ROOT'], ex.
include $_SERVER['DOCUMENT_ROOT'].'/user/codestart.php';
include $_SERVER['DOCUMENT_ROOT'].'/config/config.php';
It save you from absolute paths' problems.
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.
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".