My situation: I have a class that I want to use in a number of places, so I placed it high in the directory tree:
/www/libs/classA/classA.php
It uses a config file located in the same directory called config.ini and references it locally in the constructor. However, when I include it from a script in a different directory, it tries to load the config file from the directory the calling script is in. Is there any way I can look in the directory the included file is in? Ideally I could move the script to a different directory and not make any changes to it.
You should use the absolute path when including/loading files. And you can retrieve that absolute path with the __FILE__ constant and dirname function:
dirname(__FILE__).'/config.ini'
This will five you the absolute path of the config.ini file in the same directory the currently executed script file is located in. So when that code is executed in your classA.php script file, you would get /www/libs/classA/config.ini.
You should be able to include/require a file from the current file's directory if you have no path info in the argument, e.g. include('file2.php');. But I think even if you have './file2.php'), then it's going to become relative to the directory of the first-included/executed script.
I like the dirname(____FILE____)... method, but I believe in the case where a certain set of files is intended to always be deployed in the same directory, the direct file include promotes cohesion.
Related
I am trying to get my include() functions in order but everytime I switch the syntax in one directory it messes up its subdirectory and vice versa.
I have a file called 'header.php' in my 'localhost/FTS/includes/header.php' folder.
The 'FTS' folder has my index.php file so it is technically my root folder while I am testing.
In the file 'localhost/FTS/admin.php' I use the line include 'includes/header.php'; and it works fine but then when I go into the file 'localhost/FTS/admin/members.php' the include file is not found. Also inside of my 'header.php' file I include a couple more files from my root directory.
I just want all of my includes to work from each directory. Any ideas?
The include statement includes files relative to the script executing include, which is why you're seeing this issue. You have a couple of options available to you:
You can preface your include path with something like $_SERVER['DOCUMENT_ROOT'], which if you're using Apache, will reference your document root directory. So something like include( $_SERVER['DOCUMENT_ROOT'] . "/includes/header.php" ); will appear to the script as an absolute path, so it will work if called from various places in your structure, but still be portable (note that it would require being called from a web server, this won't work if you're using your scripts through CLI).
You can create some sort of placeholder at the root of your directory structure, and work your way up until you find it, then consider this the root and make your include statements relative to this. This will be more portable and work in CLI mode, but it will be slightly more resource intensive.
You can use different include statements depending on where you're script including the include file is located, such as include( "includes/header.php" ); if the file you're including is in the includes directory of the directory you're currently in, or include( "../includes/header.php" ); if the includes directory is in the parent directory of the script being run.
When using PHP's include() and require() functions to include a file which in turn includes another file, the PWD (relative reference) for the second file's include() is the directory for the original script location (the first script in the stack as called by Apache), not for the current file. What is the design decision behind that, and what is the use-case?
For instance, suppose a generic database-connection class defined in ~/public_html/classes/database.php which stores its configuration data (usernames, passwords) out of the web root in ~/config.php. The author of the database configuration class would logically call the config file with the relative filename ../../config.php. However, this does not work as expected because the PWD is not of the database.php file but rather of the file which included it, which could be ~/public_html/index.php, ~/public_html/someDir/somePage.php or elsewhere.
I know to work around this by getting the directory of the current file with dirname(__FILE__). However, I cannot think of a single use case where I would want require() or include() to be relative to the original script location. What is the use case for it being as it is?
The function include() and require() handle relative path the same as any other file access function like fopen(), unlink() and mkdir().
Path are always relative to PWD regardless of the location of the script.
Take the following example into consideration:
/home/foo/index.php does
require_once('lib/maketest.php');
/home/foo/lib/maketest.php does
mkdir('test');
This will create the directory /home/foo/test and not /home/foo/lib/test.
I can image that this has chosen because a bash script that does mkdir test will also create the directory $PWD/test regardless of where the script is located.
Having include() following the same logic as other file access functions makes sense. Consider the following code:
if (file_exists('config.php')) include('config.php');
If paths in include() would be relative to __DIR__ and paths in file_exists() to PWD the above code wouldn't work as expected.
PWD is short for Print Working Directory. Current working directory is abbreviated as CWD.
The CWD might change during the code execution and PHP doesn't necessarily have to include code from a local file path.
As you already knew, examining __FILE__ together with dirname() is the correct solution to your problem. You should also be defining a constant with the root path of your application and use that throughout the code instead of relying on that the working directory stays the same.
The CWD will not even be the path of your script starting point in all situations.
I have a site where the PHP include path is /usr/share/php
Within this path I have a sub-folder containing some utility files, e.g. /usr/share/php/utils. my_session.php is one of these utility files.
My application calls
require ("my_session.php");
and this works even though the file is actually within the utils folder.
I am trying to replicate this site in another installation and I am getting the error:
Failed opening required 'my_session.php' (include_path='.:/usr/share/php)
My question is:
Should the php include path also include files in sub-folders in the include path?
This appears to be the case on my original site and I don't know why the behaviour seems to be different on the second site.
According to PHP documentation when you try to include a file, only paths listed in the include_path directive are checked. PHP is not supposed to check their subfolders.
My guess would be that this fails because you are using a relative path for the require.
Your include_path is defined as .:/usr/share/php. That means only two folders will be checked when require('my_session.php') gets executed:
the current path
the folder /usr/share/php
I don't know your folder structure, so let's just imagine one:
my_project
- app
-- index.php
- lib
-- my_session.php
Now, if my_project/app/index.php tries to require('my_session.php') this will fail, because the current folder at the time executing the require is my_project/app/ and there is no file entry of my_session.php relative to my_project/app/ (it's relative to my_project/lib/ instead).
Long story short: Try to to use an absolute path instead of your relative one, e.g.
require('/var/www/html/my_project/lib/my_session.php');
Edit: removed and its subfolders, which was wrong. Too much __autoload in my brain^^
Two solutions:
Add /usr/share/php/utils to your include_path.
or
Include your file with require ("utils/my_session.php");
I'm having problems with my include files. I don't seem to be able to figure out how to construct my URLs when I use require_once('somefile.php'). If I try to use an include file in more than one place where the directory structures are different, I get an error that the include file cannot be found.
In asp.net, to get my application root path, I can use ~/directory/file.aspx. The tild forward slash always knows that I am referencing from my website root and find the file no matter where the request comes from within my website. It always refers back to the root and looks for the file from there.
QUESTION: How can I get the root path of my site? How can I do this so I can reuse my include files from anywhere within my site? Do I have to use absolute paths in my URLs?
Thank you!
There is $_SERVER['DOCUMENT_ROOT'] that should have the root path to your web server.
Edit: If you look at most major php programs. When using the installer, you usually enter in the full path to the the application folder. The installer will just put that in a config file that is included in the entire application. One option is to use an auto prepend file to set the variable. another option is to just include_once() the config file on every page you need it. Last option I would suggest is to write you application using bootstrapping which is where you funnel all requests through one file (usually with url_rewrite). This allows you to easily set/include config variables in one spot and have them be available throughout all the scripts.
I usually store config.php file in ROOT directory, and in config.php I write:
define('ROOT_DIR', __DIR__);
And then just use ROOT_DIR constant in all other scripts.
Using $_SERVER['DOCUMENT_ROOT'] is not very good because:
It's not always matching ROOT_DIR
This variable is not available in CGI mode (e.x. if you run your scripts by CRON)
It's nice to be able to use the same code at the top of every script and know that your page will load properly, even if you are in a subdirectory. I use this, which relies on you knowing what your root directory is called (typically, 'htdocs' or 'public_html':
defined('SITEROOT') or define('SITEROOT', substr($_SERVER['DOCUMENT_ROOT'], 0, strrpos($_SERVER['DOCUMENT_ROOT'], 'public_html')) . 'public_html');
With SITEROOT defined consistently, you can then access a config file and/or page components without adapting paths on a script-by-script basis e.g. to a config file stored outside your root folder:
require_once SITEROOT . "/../config.php";
You should use the built in magic constants to find files. __FILE__ and __DIR__. If you are on PHP < 5.3 you should use dirname(__FILE__)
E.g.
require_once __DIR__.'/../../include_me.php';
$_SERVER['DOCUMENT_ROOT'] is not always guaranteed to return what you would expect.
Define it in a config file somewhere.
Assuming you're using an MVC style where everything gets routed through a single index.php then
realpath('.');
Will show you the path to the current working directory (i.e where index.php is)
So then you can define this as
define('PROJECT_ROOT', realpath('.'));
If it's not MVC and you need it to work for files in subfolders then you can just hard code it in a config file
define('PROJECT_ROOT', 'C:/wamp/www/mysite');
Then when including something you can do;
include PROJECT_ROOT . '/path/to/include.php';
You could alternativly set the base directory in your .htaccess file
SetEnv BASE_PATH C:/wamp/www/mysite/
Then in PHP you can reference it with $_SERVER['BASE_PATH']
Try this:
$_SERVER['DOCUMENT_ROOT']
I am developing a web application. contents are:
root dir (/var/www/)
config.php
index.php
details.php
admin dir (/var/www/admin)
admin.php
I have included config.php file into index.php, details.php in root directory using require_once('config.php') as this file contains database passwords, styles, images directory paths..
how can i include that config files in my admin/admin.php file so that one config file can be used in anywhere(even in subdirectories) of my web application. Will it make any difference for the value of define('APP_BASE_PATH', dirname(__FILE__)); when same config file is used by all files in the web application.
if i am wrong somewhere then please get me right.
If your server properly configured, just
include $_SERVER['DOCUMENT_ROOT']."/config.php";
anywhere
You have also 2 other possible ways.
a Front controller setup, where ALL user requests going into one file. And ths one going to include all others from their subdirectories. Personally I don't like it cause this front file become a mess. Though it's widely used.
I decided not to mention it because noone would use a hardcoded full path anyway.
Update after clarification in comments: You are looking for a way to include a central configuration file from anywhere in your project's folder structure.
#Col. Shrapnel shows one way, DOCUMENT_ROOT. It's the only way to use an "absolute" path from a nested folder structure. It has the limitation I describe above, but it's fine otherwise.
If you want maximum portability (i.e. the possibility to run the app with e.g. www.example.com/myapp/version_1 as its root directory), you would have to use relative references from within your folder structure to "climb down" to the config file, e.g. ../../config.php that will work reliably too, although be a bit cumbersome e.g. if you move a script to a different folder and you have to update the relative path.
you can use the same config file every time... using "/" will take you back to the root directory... so in admin/admin.php use this:
require_once("/config.php");
you can use "../" to take you up one directory eg:
require_once("../config.php");
was this what you were looking for?