How php includes work with objects [duplicate] - php

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");

Related

PHP Include './' vs '../' [duplicate]

A. What does this do?
require ("./file.php");
B. in comparison to this?
require ("file.php");
(Its not up-one-directory.. which would be)
require ("../file.php");
./ is the current directory. It is largely the same as just file.php, but in many cases (this one included) it doesn't check any standard places PHP might look for a file, instead checking only the current directory.
From the PHP documentation (notice the last sentence):
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.
The first version forces the internal mechanism to include files relatively to the... directly executed file. So for example you have
index.php
// directly executed script (php -f index.php or from a browser)
include 'second.php';
second.php
// This is included relatively to index.php
// Actually, it is first searched relatively to include_path, then relatively
// to index.php
include './third.php';
third.php
// This is included relatively to second.php ONLY. It does not search
// include_path
return "foo";
The Short Answer
You're right, it's not up one directory. A . refers to the directory you're in, and .. refers to the parent directory.
Meaning, ./file.php and file.php are functionally equivalent in PHP. Here's the relavent page of documentation:
http://us.php.net/manual/en/wrappers.file.php
The Longer Answer
However, just because they work the same in this context doesn't mean they're always the same.
When you're operating in a *nix shell environment, and you type the name of an executable file, the shell will look in the PATH directories, but it won't look in the CWD, or the directory you're currently in.
So, if you're in a directory that has a file called: myprogram.php (this would be a PHP CLI file) and you just type:
myprogram.php
it doesn't matter if your program is executable or not. The shell will look in /bin/, /usr/bin/, etc. for your file, but it won't look in ./: the directory you're in.
To execute that program without adding your directory to the PATH, you need to type
./myprogram
So really, ./ is more explicit. It means, "the file you're looking for HAS to be right here" and lack of ./ means, "the file should be somewhere the program is looking for files".
The dot-slash forces the file to be found in the current directory only, rather than additionally searching the paths mentioned in the include_path setting.
Edit: I have completely rewritten the answer for the sake of clarity
When including a file, you can either use ./myfile.php or myfile.php.
They are not the same and you should always, preferably, use the first syntax, unless you know what you're doing.
The difference is best illustrated with an example: lets say you have the following files and folder structure:
index.php
inc/inner.php
From index.php, you can include your inner template without the ' ./' and it will work as expected:
# index.php
<?php
include "inc/inner.php";
Now let's say we add a new file, so the folder structure is now like this:
index.php
inc/inner.php
inc/inner-inner.php
To include inner-inner.php in inner.php, we would do this... right?
# src/inner.php
<?php
include "inner-inner.php";
Wrong. inner.php will just look for inner-inner.php in the root folder.
index.php
* inner-inner.php <- Doesn't exist, PHP ERROR.
inc/inner.php
inc/inner-inner.php
Instead, we should use the ./ syntax to include inner-inner. This will instruct that the file we are including must be included relative to the current file, not to the current "entry point" of the PHP script (index.php in the example).
# src/inner.php
<?php
include "./inner-inner.php";
In addition, and as mentioned in other comments, if you have configured a different "load path" for your PHP application, that load path will be looked up first without the ./ syntax. Instead, the ./ syntax is more efficient because it doesn't check the "include path" of php 1.
If you wanna make your includes even more explicit, use the __DIR__ constant. This tells php: "Use the directory of this file" 2.
# src/inner.php
<?php
include __DIR__ . "/inner-inner.php";
TLDR; Always use ./ or __DIR__ 2 because it's relative to the current (working) directory and doesn't depend on the PHP "include path" 1.
References:
[Include - https://www.php.net/manual/en/function.include.php]
Magic Constants - https://www.php.net/manual/en/language.constants.magic.php
Simply you are telling php to include the file in the current directory only or fail if the file is not present.
If you use the format "indexcommon3.php" and the file is not present php will search it into the include_path system variable.
For reference you can use http://www.php.net/manual/en/function.include.php
It's explicitly naming the current directory.

"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");

PHP will include a file relative to a calling script, but not if the include path contains "../"

From what I gather from PHP's documentation and from other posts here, PHP's include (and include_once) do the following:
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
I have the following structure in a given directory:
index.php
/dirA (contains a.php and b.php)
/dirB (contains c.php)
From index.php include_once "dirA/a.php"
Here's what works from within a.php:
include_once "b.php"
include_once "dirB/c.php"
Here's what DOESN"T work from within a.php:
include_once "b.php"
include_once "../dirB/c.php"
The curious thing to me is that b.php is included relative to the "calling script's own directory" but c.php is only considered relative to the current working directory (which is the dir containing index.php). This seems to be a slight inconsistency to me. PHP will include a file relative to a calling script, but not if the include path contains ../ - why? Why won't the ../ parent directory directive work relative to the calling script but it will relative to the current working directory? (note: I tested it relative to the cwd but didn't include that file in my example above just to keep it cleaner. It worked just fine)
Can anyone shed some light as to why this is? Should it work this way, or is this a bug?
PHP's a bit odd in how it looks for files. If you include a file whose name starts with a slash or a dot, PHP ignores the include_path entirely. If a dot, it assumes the name is relative to the script that kicked off everything (ie: the one the web server decided to run).
If you want to specify a path relative to the included script and not the startup one, what you really want is an absolute include that specifies the full name of the file. That's easy to do with the __FILE__ and __DIR__ constants, which reflect the name and directory of the currently running script.
include __DIR__ . '/../dirB/c.php';
If you like, you can also set the include_path config setting to include the root of the app, and just specify all filenames relative to that.
It is because you have first included the dirA/a.php to index.php , so from now on the index.php is your base file from which all includes are taking place. And therefore if you include c.php from a.php it is like you do it from index.php
And that's why you are getting wrong results if you specify one level up with "../" . It searches one level above index.php and it finds nothing.

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");

What does the dot-slash do to PHP include calls?

A. What does this do?
require ("./file.php");
B. in comparison to this?
require ("file.php");
(Its not up-one-directory.. which would be)
require ("../file.php");
./ is the current directory. It is largely the same as just file.php, but in many cases (this one included) it doesn't check any standard places PHP might look for a file, instead checking only the current directory.
From the PHP documentation (notice the last sentence):
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.
The first version forces the internal mechanism to include files relatively to the... directly executed file. So for example you have
index.php
// directly executed script (php -f index.php or from a browser)
include 'second.php';
second.php
// This is included relatively to index.php
// Actually, it is first searched relatively to include_path, then relatively
// to index.php
include './third.php';
third.php
// This is included relatively to second.php ONLY. It does not search
// include_path
return "foo";
The Short Answer
You're right, it's not up one directory. A . refers to the directory you're in, and .. refers to the parent directory.
Meaning, ./file.php and file.php are functionally equivalent in PHP. Here's the relavent page of documentation:
http://us.php.net/manual/en/wrappers.file.php
The Longer Answer
However, just because they work the same in this context doesn't mean they're always the same.
When you're operating in a *nix shell environment, and you type the name of an executable file, the shell will look in the PATH directories, but it won't look in the CWD, or the directory you're currently in.
So, if you're in a directory that has a file called: myprogram.php (this would be a PHP CLI file) and you just type:
myprogram.php
it doesn't matter if your program is executable or not. The shell will look in /bin/, /usr/bin/, etc. for your file, but it won't look in ./: the directory you're in.
To execute that program without adding your directory to the PATH, you need to type
./myprogram
So really, ./ is more explicit. It means, "the file you're looking for HAS to be right here" and lack of ./ means, "the file should be somewhere the program is looking for files".
The dot-slash forces the file to be found in the current directory only, rather than additionally searching the paths mentioned in the include_path setting.
Edit: I have completely rewritten the answer for the sake of clarity
When including a file, you can either use ./myfile.php or myfile.php.
They are not the same and you should always, preferably, use the first syntax, unless you know what you're doing.
The difference is best illustrated with an example: lets say you have the following files and folder structure:
index.php
inc/inner.php
From index.php, you can include your inner template without the ' ./' and it will work as expected:
# index.php
<?php
include "inc/inner.php";
Now let's say we add a new file, so the folder structure is now like this:
index.php
inc/inner.php
inc/inner-inner.php
To include inner-inner.php in inner.php, we would do this... right?
# src/inner.php
<?php
include "inner-inner.php";
Wrong. inner.php will just look for inner-inner.php in the root folder.
index.php
* inner-inner.php <- Doesn't exist, PHP ERROR.
inc/inner.php
inc/inner-inner.php
Instead, we should use the ./ syntax to include inner-inner. This will instruct that the file we are including must be included relative to the current file, not to the current "entry point" of the PHP script (index.php in the example).
# src/inner.php
<?php
include "./inner-inner.php";
In addition, and as mentioned in other comments, if you have configured a different "load path" for your PHP application, that load path will be looked up first without the ./ syntax. Instead, the ./ syntax is more efficient because it doesn't check the "include path" of php 1.
If you wanna make your includes even more explicit, use the __DIR__ constant. This tells php: "Use the directory of this file" 2.
# src/inner.php
<?php
include __DIR__ . "/inner-inner.php";
TLDR; Always use ./ or __DIR__ 2 because it's relative to the current (working) directory and doesn't depend on the PHP "include path" 1.
References:
[Include - https://www.php.net/manual/en/function.include.php]
Magic Constants - https://www.php.net/manual/en/language.constants.magic.php
Simply you are telling php to include the file in the current directory only or fail if the file is not present.
If you use the format "indexcommon3.php" and the file is not present php will search it into the include_path system variable.
For reference you can use http://www.php.net/manual/en/function.include.php
It's explicitly naming the current directory.

Categories