PHP Pathing issues - php

I'm a bit confused, so any answer that you can come up with that will help me get started to look where the problem is will help.
I have /folder1/API.php using: require_once('../folder2/Core.php');
I then have /folder1/Panel.php using: require_once('folder2/Core.php'); (note that there is no '..').
Somehow, both API.php and Panel.php are able to locate Core.php even though they are in the same folder but different require_once parameters.
Even weirder: in /folder2/Core.php, there's require_once('../folder3/DBConfig.php'); in which API.php is able to go through, but when calling a function from Panel.php, it says that I cannot find '../folder3/DBConfig.php'.

Require (and include) will search in your include path too, perhaps the folders are included there.
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.
http://www.php.net/manual/en/function.include.php

Keep in mind that .. say index.php includes a file test.php which is in another folder.
test.php has some includes with relative paths to other files.
Since test.php is included in index.php, all the relative paths in it will be computed relative to index.php (so most will be broken)
1 more thing:
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() /and likewise require/ will finally check in the calling script's own directory and the current working directory before failing.

Related

"include" not working when references files outside of my current folder? [duplicate]

I'm having trouble understanding the ruleset regarding PHP relative include paths. If I run file A.PHP- and file A.PHP includes file B.PHP which includes file C.PHP, should the relative path to C.PHP be in relation to the location of B.PHP, or to the location of A.PHP? That is, does it matter which file the include is called from, or only what the current working directory is- and what determines the current working directory?
It's relative to the main script, in this case A.php. Remember that include() just inserts code into the currently running script.
That is, does it matter which file the include is called from
No.
If you want to make it matter, and do an include relative to B.php, use the __FILE__ constant (or __DIR__ since PHP 5.2 IIRC) which will always point to the literal current file that the line of code is located in.
include(dirname(__FILE__)."/C.PHP");
#Pekka got me there, but just want to share what I learned:
getcwd() returns the directory where the file you started executing resides.
dirname(__FILE__) returns the directory of the file containing the currently executing code.
Using these two functions, you can always build an include path relative to what you need.
e.g., if b.php and c.php share a directory, b.php can include c.php like:
include(dirname(__FILE__).'/c.php');
no matter where b.php was called from.
In fact, this is the preferred way of establishing relative paths, as the extra code frees PHP from having to iterate through the include_path in the attempt to locate the target file.
Sources:
Difference Between getcwd() and dirname(__FILE__) ? Which should I use?
Why you should use dirname(__FILE__)
The accepted answer of Pekka is incomplete and, in a general context, misleading. If the file is provided as a relative path, the called language construct include will search for it in the following way.
First, it will go through the paths of the environment variable include_path, which can be set with ini_set. If this fails, it will search in the calling script's own directory dirname(__FILE__) (__DIR__ with php >= 5.3.) If this also fails, only then it will search in the working directory ! It just turns out that, by default, the environment variable include_path begins with ., which is the current working directory. That is the only reason why it searches first in the current working directory. See http://php.net/manual/en/function.include.php.
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.
So, the correct answer to the first part of the question is that it does matter where is located the included calling script. The answer to the last part of the question is that the initial working directory, in a web server context, is the directory of the called script, the script that includes all the others while being handled by PHP. In a command line context, the initial working directory is whatever it is when php is invoked at the prompt, not necessarily the directory where the called script is located. The current working directory, however, can be changed at run time with the PHP function chdir. See http://php.net/manual/en/function.chdir.php.
This paragraph is added to comment on other answers. Some have mentioned that relying on include_path is less robust and thus it is preferable to use full paths such as ./path or __DIR__ . /path. Some went as far as saying that relying on the working directory . itself is not safe, because it can be changed. However, some times, you need to rely on environment values. For example, you might want set include_path empty, so that the directory of the calling script is the first place that it will search, even before the current working directory. The code might be already written and updated regularly from external sources and you do not want to reinsert the prefix __DIR__ each time the code is updated.
If include path doesn't start with ./ or ../, e.g.:
include 'C.php'; // precedence: include_path (which include '.' at first),
// then path of current `.php` file (i.e. `B.php`), then `.`.
If include path starts with ./ or ../, e.g.:
include './C.php'; // relative to '.'
include '../C.php'; // also relative to '.'
The . or .. above is relative to getcwd(), which defaults to the path of the entry .php file (i.e. A.php).
Tested on PHP 5.4.3 (Build Date : May 8 2012 00:47:34).
(Also note that chdir() can change the output of getcwd().)
Short answer: it's relative to the including script.
TFM explains it correctly:
If the file isn't found in the include_path, include will check in the calling script's directory and the current working directory
So, if /app/main.php says include("./inc.php") that will find /app/inc.php.
The ./ is not strictly necessary but removes any dependency on include_path.
I would not rely on finding include files in the current working directory in case someone changes it with chdir().
dir
-> a.php
-> c.php
- dir2
-> b.php
To include a in b you need to include("../a.php");
To include b in c you need to include("dir2/b.php");

Warning: require_once(/HTML/Template/ITX.php): failed to open stream: No such file or directory in C:\wamp64\www\mysite\main\login.php on line 13 [duplicate]

I was writing an web app in PHP, when I encountered a strange situation. To illustrate my problem, consider a web app of this structure:
/
index.php
f1/
f1.php
f2/
f2.php
Contents of these files:
index.php:
<?php require_once("f1/f1.php"); ?>
f1.php:
<?php require_once("../f2/f2.php"); ?>
f2.php: blank
now when I try to open index.php in my browser I get this error:
Warning: require_once(../f2/f2.php) [function.require-once]:
failed to open stream: No such file or directory in /var/www/reqtest/f1/f1.php on line 2
Fatal error: require_once() [function.require]:
Failed opening required '../f2/f2.php' (include_path='.:/usr/share/php:/usr/share/pear') in /var/www/reqtest/f1/f1.php on line 2
Is there something obvious I'm missing? how do include paths work in PHP?
Before I asked this question, I attempted to experiment and find out. I set up another test, like so:
/
index.php
f1/
f1.php
f2.php
index.php:
<?php require_once("f1/f1.php"); ?>
f1.php:
<?php require_once("f2.php"); ?>
f2.php: blank
To my surprise (and utter confusion), this worked out fine!
So, what is the secret behind the path resolution?
PS I saw this question, but it still does not answer the second case that I've stated here.
If you include another file, the working directory remains where the including file is.
Your examples are working as intended.
Edit: The second example works because . (actual directory) is in your include path (see your error message).
Edit2:
In your second example, the key point of your interest is this line:
<?php require_once("f2.php"); ?>
At first it will look in the current working dir (/var/www/req_path_test), but does not find f2.php.
As fallback, it will try to find f2.php in your include_path ('.:/usr/share/php:/usr/share/pear'), starting with '.' (which is relative to the actual file, not the including one).
So './f2.php' works and the require does not fail.
When you open index.php, working dir is set to the folder this file resides in. And inside insluded f1.php this working dir does not change.
You can include files by using their absolute paths, relative to the current included file like this:
require_once(dirname(__FILE__).'/../../test/file.php')
But better consider using an autoloader if these files contain classes.
Normaly in you old structure
<?php require_once("f2/f2.php"); ?>
instead of
<?php require_once("../f2/f2.php"); ?>
should work. As far as i know php takes the paths from the initial script
It sounds like your server has the open_basedir setting enabled in the PHP configuration. This makes it impossible to include (and open) files in folders above your in the directory structur (i.e., you can't use ../ to go up in the folder structure).
From the PHP Docs PHP include
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.
If the file path is not given then i.e require_once("f2.php");
1st. The include_path is checked
2nd. The calling scripts own directory is checked
3rd. Finally the current working directory is checked
If file not found then PHP throws warning on file include & fatal error on require
If a path is defined — whether absolute (starting with a drive letter or \ on Windows, or / on Unix/Linux systems) or relative to the current directory (starting with . or ..) — the include_path will be ignored altogether. For example, if a filename begins with ../, the parser will look in the parent directory to find the requested file.
If you include/require your file beginning with . or .. or ./ then PHP's parser will look in the parent directory which is the current working directory i.e require_once("../f2/f2.php"), php will check at the root directory as the calling script index.php is in that directory.
Now You have not defined any include path in your PHP script thus it always falls back to the calling script and then into the current working directory.
// Check your default include path, most likely to be C:\xampp\php\PEAR
echo get_include_path();
// To set include path
set_include_path ( string $new_include_path ) : string
The Current Working Directory is derived from your main calling script index.php.
// The Current Working Directory can be checked
echo getcwd();
In the first Example where the required file "../f2/f2.php" is from f1.php
You code does not work because -
The specified path is ignored by PHP as your filename begins with ../
f1/ the calling script's own directory is ignored as well.
The parser directory looks into the parent directory to find the requested file. The current working directory is root directory, this is from where you have initiated the working script index.php. The file is not located at this directory, wrong path given.
Thus you get the Fatal Error
In the Second example you have changed the directory & from f1.php you require_once("f2.php").
Your code works because -
This time you require("f2.php") no leading ../ or ./ This time PHP checks the include_path but does find it there, as you haven't defined it and the file does not reside in the default preset include_path.
This time the calling script f1.php's directory is f1/. and you require file ("f2.php") is located at this directory. PHP This time checks the file in this directory and finds it.
PHP does not have to check the working directory as the file was found.
Thus Your Code Works Fine!

PHP Polymorphic Root Requires

I have a directory/file tree as follows:
index.php
/frame/main_class.php
/frame/func/function_1.php
/frame/func/function_1.php
/cfg/config.php
//index.php
require('frame/main_class.php');
new main_class;
//frame/main_class.php
class main_class{
public function __construct(){
require('func/function_1.php');
require('func/function_2.php');
require('cfg/config.php');
}
}
The weird part is that it works. Maybe it is late and I am having a dumb-moment, but shouldn't "require('cfg/config');" be written "require('../cfg/config.php');" ?
And if it is using the root of index.php, then "require('func/function_1.php');" shouldn't work, right?
I have quadruple checked the remote server thinking that maybe there was a stray file or two... there isn't.
How can the two require statements have a different base path.....?
Does anyone know of a code snippet that could cause this to happen? I am working with some $_SERVER variables but I don't appear to be changing any of them....!?
"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." Explicitly saying include dirname(__FILE__) . '/path/to/file.php';avoids this confusion. – DCoder
Link to PHP Manual on "dirname".
The PHP engine will look for the requested files in the current directory, but it will also look for them in the list of paths defined in INCLUDE_PATH. If the include path lists the path from where your script is running then the given code will work. If not then it wont.
For that reason amongst others it's not a good idea to rely on the include path to resolve the path of included files. You should give the full path instead.

Are PHP include paths relative to the file or the calling code?

I'm having trouble understanding the ruleset regarding PHP relative include paths. If I run file A.PHP- and file A.PHP includes file B.PHP which includes file C.PHP, should the relative path to C.PHP be in relation to the location of B.PHP, or to the location of A.PHP? That is, does it matter which file the include is called from, or only what the current working directory is- and what determines the current working directory?
It's relative to the main script, in this case A.php. Remember that include() just inserts code into the currently running script.
That is, does it matter which file the include is called from
No.
If you want to make it matter, and do an include relative to B.php, use the __FILE__ constant (or __DIR__ since PHP 5.2 IIRC) which will always point to the literal current file that the line of code is located in.
include(dirname(__FILE__)."/C.PHP");
#Pekka got me there, but just want to share what I learned:
getcwd() returns the directory where the file you started executing resides.
dirname(__FILE__) returns the directory of the file containing the currently executing code.
Using these two functions, you can always build an include path relative to what you need.
e.g., if b.php and c.php share a directory, b.php can include c.php like:
include(dirname(__FILE__).'/c.php');
no matter where b.php was called from.
In fact, this is the preferred way of establishing relative paths, as the extra code frees PHP from having to iterate through the include_path in the attempt to locate the target file.
Sources:
Difference Between getcwd() and dirname(__FILE__) ? Which should I use?
Why you should use dirname(__FILE__)
The accepted answer of Pekka is incomplete and, in a general context, misleading. If the file is provided as a relative path, the called language construct include will search for it in the following way.
First, it will go through the paths of the environment variable include_path, which can be set with ini_set. If this fails, it will search in the calling script's own directory dirname(__FILE__) (__DIR__ with php >= 5.3.) If this also fails, only then it will search in the working directory ! It just turns out that, by default, the environment variable include_path begins with ., which is the current working directory. That is the only reason why it searches first in the current working directory. See http://php.net/manual/en/function.include.php.
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.
So, the correct answer to the first part of the question is that it does matter where is located the included calling script. The answer to the last part of the question is that the initial working directory, in a web server context, is the directory of the called script, the script that includes all the others while being handled by PHP. In a command line context, the initial working directory is whatever it is when php is invoked at the prompt, not necessarily the directory where the called script is located. The current working directory, however, can be changed at run time with the PHP function chdir. See http://php.net/manual/en/function.chdir.php.
This paragraph is added to comment on other answers. Some have mentioned that relying on include_path is less robust and thus it is preferable to use full paths such as ./path or __DIR__ . /path. Some went as far as saying that relying on the working directory . itself is not safe, because it can be changed. However, some times, you need to rely on environment values. For example, you might want set include_path empty, so that the directory of the calling script is the first place that it will search, even before the current working directory. The code might be already written and updated regularly from external sources and you do not want to reinsert the prefix __DIR__ each time the code is updated.
If include path doesn't start with ./ or ../, e.g.:
include 'C.php'; // precedence: include_path (which include '.' at first),
// then path of current `.php` file (i.e. `B.php`), then `.`.
If include path starts with ./ or ../, e.g.:
include './C.php'; // relative to '.'
include '../C.php'; // also relative to '.'
The . or .. above is relative to getcwd(), which defaults to the path of the entry .php file (i.e. A.php).
Tested on PHP 5.4.3 (Build Date : May 8 2012 00:47:34).
(Also note that chdir() can change the output of getcwd().)
Short answer: it's relative to the including script.
TFM explains it correctly:
If the file isn't found in the include_path, include will check in the calling script's directory and the current working directory
So, if /app/main.php says include("./inc.php") that will find /app/inc.php.
The ./ is not strictly necessary but removes any dependency on include_path.
I would not rely on finding include files in the current working directory in case someone changes it with chdir().
dir
-> a.php
-> c.php
- dir2
-> b.php
To include a in b you need to include("../a.php");
To include b in c you need to include("dir2/b.php");

How does include path resolution work in require_once?

I was writing an web app in PHP, when I encountered a strange situation. To illustrate my problem, consider a web app of this structure:
/
index.php
f1/
f1.php
f2/
f2.php
Contents of these files:
index.php:
<?php require_once("f1/f1.php"); ?>
f1.php:
<?php require_once("../f2/f2.php"); ?>
f2.php: blank
now when I try to open index.php in my browser I get this error:
Warning: require_once(../f2/f2.php) [function.require-once]:
failed to open stream: No such file or directory in /var/www/reqtest/f1/f1.php on line 2
Fatal error: require_once() [function.require]:
Failed opening required '../f2/f2.php' (include_path='.:/usr/share/php:/usr/share/pear') in /var/www/reqtest/f1/f1.php on line 2
Is there something obvious I'm missing? how do include paths work in PHP?
Before I asked this question, I attempted to experiment and find out. I set up another test, like so:
/
index.php
f1/
f1.php
f2.php
index.php:
<?php require_once("f1/f1.php"); ?>
f1.php:
<?php require_once("f2.php"); ?>
f2.php: blank
To my surprise (and utter confusion), this worked out fine!
So, what is the secret behind the path resolution?
PS I saw this question, but it still does not answer the second case that I've stated here.
If you include another file, the working directory remains where the including file is.
Your examples are working as intended.
Edit: The second example works because . (actual directory) is in your include path (see your error message).
Edit2:
In your second example, the key point of your interest is this line:
<?php require_once("f2.php"); ?>
At first it will look in the current working dir (/var/www/req_path_test), but does not find f2.php.
As fallback, it will try to find f2.php in your include_path ('.:/usr/share/php:/usr/share/pear'), starting with '.' (which is relative to the actual file, not the including one).
So './f2.php' works and the require does not fail.
When you open index.php, working dir is set to the folder this file resides in. And inside insluded f1.php this working dir does not change.
You can include files by using their absolute paths, relative to the current included file like this:
require_once(dirname(__FILE__).'/../../test/file.php')
But better consider using an autoloader if these files contain classes.
Normaly in you old structure
<?php require_once("f2/f2.php"); ?>
instead of
<?php require_once("../f2/f2.php"); ?>
should work. As far as i know php takes the paths from the initial script
It sounds like your server has the open_basedir setting enabled in the PHP configuration. This makes it impossible to include (and open) files in folders above your in the directory structur (i.e., you can't use ../ to go up in the folder structure).
From the PHP Docs PHP include
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.
If the file path is not given then i.e require_once("f2.php");
1st. The include_path is checked
2nd. The calling scripts own directory is checked
3rd. Finally the current working directory is checked
If file not found then PHP throws warning on file include & fatal error on require
If a path is defined — whether absolute (starting with a drive letter or \ on Windows, or / on Unix/Linux systems) or relative to the current directory (starting with . or ..) — the include_path will be ignored altogether. For example, if a filename begins with ../, the parser will look in the parent directory to find the requested file.
If you include/require your file beginning with . or .. or ./ then PHP's parser will look in the parent directory which is the current working directory i.e require_once("../f2/f2.php"), php will check at the root directory as the calling script index.php is in that directory.
Now You have not defined any include path in your PHP script thus it always falls back to the calling script and then into the current working directory.
// Check your default include path, most likely to be C:\xampp\php\PEAR
echo get_include_path();
// To set include path
set_include_path ( string $new_include_path ) : string
The Current Working Directory is derived from your main calling script index.php.
// The Current Working Directory can be checked
echo getcwd();
In the first Example where the required file "../f2/f2.php" is from f1.php
You code does not work because -
The specified path is ignored by PHP as your filename begins with ../
f1/ the calling script's own directory is ignored as well.
The parser directory looks into the parent directory to find the requested file. The current working directory is root directory, this is from where you have initiated the working script index.php. The file is not located at this directory, wrong path given.
Thus you get the Fatal Error
In the Second example you have changed the directory & from f1.php you require_once("f2.php").
Your code works because -
This time you require("f2.php") no leading ../ or ./ This time PHP checks the include_path but does find it there, as you haven't defined it and the file does not reside in the default preset include_path.
This time the calling script f1.php's directory is f1/. and you require file ("f2.php") is located at this directory. PHP This time checks the file in this directory and finds it.
PHP does not have to check the working directory as the file was found.
Thus Your Code Works Fine!

Categories