require_once not working as I expect it to [duplicate] - php

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
relative path in require_once doesn’t work
I have a project structure as such:
ProjectName/
src
test
TestClass.php
tests
TestTestClass.php
WhenI try and do require_once '/ProjectName/src/test/TestClass.php'; into tests/TestTestClass.php I get an error from PHP stating that: no such file or directory.
I have checked the spelling, I have checked everything. I cannot give it the full /home/userName/bla/bla path as I need to hand this off to some one else.
Any ideas?

This is expected behaviour. When you execute TestTestClass.php, your working directory is set to ProjectName/tests.
It would be better to use ../src/test/TestClass.php.
Your path is actually absolute, so you will be working straight from /, which is not what you're expecting. If your include_path is set to your server's directory root, then your code will work without the first /. If you don't wish to rely on include_path or arbitrary levelling (with ..), you can always set an environment variable in your first file that defines the full path to your application root, then use that for all includes.
For example, /ProjectName/index.php:
define('APPPATH', __DIR__);
.. and in /ProjectName/tests/TestTestClass.php:
require_once APPPATH . '/src/test/TestClass.php';

absolute filepaths passed to require/include/require_once/include_once all work from the filesystem root, not to the webserver root

Use the special DIR to get the current path of the script and like so it will be easier for you to find script paths:
require_once(__DIR__ . '../folder/whatever.php');

You'd benefit from creating a path constant for your project. This is quiet easy to do with the __FILE__ constant and dirname().
define('ROOT_PATH', dirname(__FILE__));
The above could be put in a configuration file so it is easier to include files throughout your project.
require_once ROOT_PATH . '/src/test/TestClass.php';
I'd also suggest looking into an autoloader.

Related

Why would I use dirname(__FILE__) in an include or include_once statement?

I have seen this:
<?php
include( dirname(__FILE__) . DIRECTORY_SEPARATOR . 'my_file.php');
?>
Why would I ever need to do this? Why would I go to the trouble of getting the dirname and then concatenating that with a directory separator, and a new filename?
Is the code above not equivalent to this:
<?php
include( 'my_file.php' );
?>
??
The PHP doc says,
Files are included based on the file path given or, if none is given, the include_path specified. If the file isn't found in the include_path, include() will finally check in the calling script's own directory and the current working directory before failing. The include() construct will emit a warning if it cannot find a file; this is different behavior from require(), which will emit a fatal error.
Let's say I have a (fake) directory structure like:
.../root/
/app
bootstrap.php
/scripts
something/
somescript.php
/public
index.php
Now assume that bootstrap.php has some code included for setting up database connections or some other kind of boostrapping stuff.
Assume you want to include a file in boostrap.php's folder called init.php. Now, to avoid scanning the entire include path with include 'init.php', you could use include './init.php'.
There's a problem though. That ./ will be relative to the script that included bootstrap.php, not bootstrap.php. (Technically speaking, it will be relative to the working directory.)
dirname(__FILE__) allows you to get an absolute path (and thus avoid an include path search) without relying on the working directory being the directory in which bootstrap.php resides.
(Note: since PHP 5.3, you can use __DIR__ in place of dirname(__FILE__).)
Now, why not just use include 'init.php';?
As odd as it is at first though, . is not guaranteed to be in the include path. Sometimes to avoid useless stat()'s people remove it from the include path when they are rarely include files in the same directory (why search the current directory when you know includes are never going to be there?).
Note: About half of this answer is address in a rather old post: What's better of require(dirname(__FILE__).'/'.'myParent.php') than just require('myParent.php')?
I might have even a simpler explanation to this question compared to the accepted answer so I'm going to give it a go: Assume this is the structure of the files and directories of a project:
Project root directory:
file1.php
file3.php
dir1/
file2.php
(dir1 is a directory and file2.php is inside it)
And this is the content of each of the three files above:
//file1.php:
<?php include "dir1/file2.php"
//file2.php:
<?php include "../file3.php"
//file3.php:
<?php echo "Hello, Test!";
Now run file1.php and try to guess what should happen. You might expect to see "Hello, Test!", however, it won't be shown! What you'll get instead will be an error indicating that the file you have requested(file3.php) does not exist!
The reason is that, inside file1.php when you include file2.php, the content of it is getting copied and then pasted back directly into file1.php which is inside the root directory, thus this part "../file3.php" runs from the root directory and thus goes one directory up the root! (and obviously it won't find the file3.php).
Now, what should we do ?!
Relative paths of course have the problem above, so we have to use absolute paths. However, absolute paths have also one problem. If you (for example) copy the root folder (containing your whole project) and paste it in anywhere else on your computer, the paths will be invalid from that point on! And that'll be a REAL MESS!
So we kind of need paths that are both absolute and dynamic(Each file dynamically finds the absolute path of itself wherever we place it)!
The way we do that is by getting help from PHP, and dirname() is the function to go for, which gives the absolute path to the directory in which a file exists in. And each file name could also be easily accessed using the __FILE__ constant. So dirname(__FILE__) would easily give you the absolute (while dynamic!) path to the file we're typing in the above code. Now move your whole project to a new place, or even a new system, and tada! it works!
So now if we turn the project above to this:
//file1.php:
<?php include(dirname(__FILE__)."/dir1/file2.php");
//file2.php:
<?php include(dirname(__FILE__)."/../file3.php");
//file3.php:
<?php echo "Hello, Test!";
if you run it, you'll see the almighty Hello, Test!! (hopefully, if you've not done anything else wrong).
It's also worth mentioning that from PHP5, a nicer way(with regards to readability and preventing eye boilage!) has been provided by PHP as well which is the constant __DIR__ which does exactly the same thing as dirname(__FILE__)!
Hope that helps.
I used this below if this is what you are thinking. It it worked well for me.
<?php
include $_SERVER['DOCUMENT_ROOT']."/head_lib.php";
?>
What I was trying to do was pulla file called /head_lib.php from the root folder. It would not pull anything to build the webpage. The header, footer and other key features in sub directories would never show up. Until I did above it worked like a champ.
If you want code is running on multiple servers with different environments,then we have need
to use dirname(FILE) in an include or include_once statement.
reason is follows.
1. Do not give absolute path to include files on your server.
2. Dynamically calculate the full path like absolute path.
Use a combination of dirname(FILE) and subsequent calls to itself until you reach to the home of your '/myfile.php'.
Then attach this variable that contains the path to your included files.

How do you developers set your paths for templates?

I thought I would ask in case I could do it a better way.
On my local (WAMP) I have all my website in the www folder. ( C:\wamp\www )
Now currently I do this when i include a file:
require_once("".$_SERVER['DOCUMENT_ROOT']."/lib/config.php");
When I am working on local and upload site to a webhost i want to ensure the paths don't breakI
Could someone please tell me if I should be doing it this way?
I want to ensure maximum compatibility; meaning that paths won't break if I, for example, move site from local to whatever web host I decided to use or if I, for example, move from one host to another.
Maybe there is a more bullet proof way of doing it?
The problem with using $_SERVER['DOCUMENT_ROOT'] is that it will break if you move your PHP scripts up or down a directory level. Instead use this:
require_once(dirname(__FILE__) . "/lib/config.php");
__FILE__ is the absolute path of the script. dirname() removes the last path component (the script filename) so you can append other path components to it, like /lib/config.php or /../../lib/config.php or whatever. This will work everywhere.
PHP 5.3 introduced a shorthand for dirname(__FILE__), called __DIR__, but this doesn't work in <5.3.
You should see Include path. For that set_include_path is useful.
What I usually do, is make 1 config file (which might include others) with a few very basic constants:
define('PROJECT_ROOT', dirname(dirname(__FILE__))); // or dirname(__DIR__) for PHP 5.3
define('PROJECT_WEB', $_SERVER['DOCUMENT_ROOT']);
// etc
Al my other files/includes will be based on those very simple constants. I will never need relative paths and never the include_path, because both PROJECT_ROOT and PROJECT_WEB are 'real'/absolute.
Other useful (?) constants would be PROJECT_LOGIC and/or PROJECT_CONTROLLERS and/or PROJECT_3RD_PARTY etc.
That works fine for including the config file (although i would get rid of the beginning quotes)
require_once( $_SERVER['DOCUMENT_ROOT'] . "/lib/config.php" );
This is really the only way to do it if you are including the config file from a bunch of different directories.
On bigger project id say that "most" developers have a front controller that all scripts are loaded from. This front controller loads the config file and since its the same file always including the config file there's no need for $_SERVER['DOCUMENT_ROOT'].

PHP how to find application root?

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']

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".

How do you know the correct path to use in a PHP require_once() statement

As many do I have a config.php file in the root of a web app that I want to include in almost every other php file. So most of them have a line like:
require_once("config.php");
or sometimes
require_once("../config.php");
or even
require_once("../../config.php");
But I never get it right the first time. I can't figure out what php is going to consider to be the current working directory when reading one of these files. It is apparently not the directory where the file containing the require_once() call is made because I can have two files in the same directory that have different paths for the config.php.
How I have a situation where one path is correct for refreshing the page but an ajax can that updates part of the page requires a different path to the config.php in the require_once() statement;
What's the secret? From where is that path evaluated?
Shoot, I was afraid this wouldn't be a common problem - This is occurring under apache 2.2.8 and PHP 5.2.6 running on windows.
The current working directory for PHP is the directory in which the called script file is located. If your files looked like this:
/A
foo.php
tar.php
B/
bar.php
If you call foo.php (ex: http://example.com/foo.php), the working directory will be /A/. If you call bar.php (ex: http://example.com/B/bar.php), the working directory will be /A/B/.
There is where it gets tricky. Let us say that foo.php is such:
<?php
require_once( 'B/bar.php' );
?>
And bar.php is:
<?php
require_once( 'tar.php');
?>
If we call foo.php, then bar.php will successfully call tar.php because tar.php and foo.php are in the same directory which happens to be the working directory. If you instead call bar.php, it will fail.
Generally you will see either in all files:
require_once( realpath( dirname( __FILE__ ) ).'/../../path/to/file.php' );
or with the config file:
// config file
define( "APP_ROOT", realpath( dirname( __FILE__ ) ).'/' );
with the rest of the files using:
require_once( APP_ROOT.'../../path/to/file.php' );
I like to do this:
require_once(dirname(__FILE__)."/../_include/header.inc");
That way your paths can always be relative to the current file location.
I use the dirname(__FILE__) thing like bobwienholt most the time, but what it could pay to do is have a base entry point that loads all your other code that defines a constant refereing to the root of the project, ie
define("ROOT",dirname(__FILE__).'/' );
and then later all you need to know is where the path is relative to root, ie:
require(ROOT . "/lib/tool/error.php");
note,
you should REALLY avoid paths with "../" at the start of them, they are not relative to the file, but relative to where you ARE and this creates broken-ass code.
cd foo
php bar/baz.php
-> some error saying it cant find the file
cd bar
php baz.php
-> suddenly working.
Important
If you use "../" notation, it takes complete ignorance of the PHP Include Path, And ONLY considers where the person whom is running it is.
I include this code at the top of every page:
//get basic page variables
$self=$_SERVER['PHP_SELF'];
$thispath=dirname($_SERVER['PHP_SELF']);
$sitebasepath=$_SERVER['DOCUMENT_ROOT'];
//include the global settings, variables and includes
include_once("$sitebasepath/globals/global.include.php");
Include and require both take either a relative path or the full rooted path. I prefer working with the full path and make all my references like the inlcude statement above. This allows me to enter a general variable $sitebasepath that handles account specific information that may change from machine to machine and then simply type the path from the webroot, ie. /globals/whatever_file.php
I also use the $self variable in forms that may call themselves to handle data input.
Hope that helps.
If you have sufficient access rights, try to modify PHP's include_path setting for the whole site. If you cannot do that, you'll either have to route every request through the same PHP script (eg. using Apache mod_rewrite) or you'll have to use an "initialization" script that sets up the include_path:
$includeDir = realpath(dirname(__FILE__) . '/include');
ini_set('include_path', $includeDir . PATH_SEPARATOR . ini_get('include_path'));
After that file is included, use paths relative to the include directory:
require_once '../init.php'; // The init-script
require_once 'MyFile.php'; // Includes /include/MyFile.php
Since require and require_once are very similar to include and include_once, all the documentation is posted under the "include" functions doc area on php.net From that page
Files for including are first looked
for in each include_path entry
relative to the current working
directory, and then in the directory
of current script. E.g. if your
include_path is libraries, current
working directory is /www/, you
included include/a.php and there is
include "b.php" in that file, b.php
is first looked in /www/libraries/
and then in /www/include/. If filename
begins with ./ or ../, it is looked
only in the current working directory.
Further, you can find all the current include paths by doing a "php -i" from the command line. You can edit the include path in your php.ini file, and also via ini_set(). You can also run the php_info() function in your page to get a printout of your env vars if the CLI is inconvenient.
The only place I've seen the path evaluated from is the file that you are currently editing. I've never had any problems with it, but if you are, you might want to provide more information (PHP version, OS, etc).
The path of the PHP file requested in the original GET or POST is essentially the 'working directory' of that script. Any "included" or "required" scripts will inherit that as their working directory as well.
I will either use absolute paths in require statements or modify PHP's include_path to include any path in my app I may want to use to save me the extra typing. You'll find that in php.ini.
include_path = ".:/list/of/paths/:/another/path/:/and/another/one"
I don't know if it'll help you out in this particular instance but the magical constants like FILE and DIR can come in handy if you ever need to know the path a particular file is running in.
http://us2.php.net/manual/en/language.constants.predefined.php
Take a look at the function getcwd. http://us2.php.net/getcwd

Categories