PHP include file that includes a file up the directory tree - php

I have this directory tree:
test.php
foodir
`---- foo.php
bardir
`---- bar.php
When I open test.php, I include foo.php. Then, I want foo.php to include bar.php.
test.php:
include 'foodir/foo.php';
foo.php:
include '../bardir/bar.php';
However, when I open test.php, I get:
Warning: include(../bardir/bar.php): failed to open stream: No such file or directory
I noticed that if I change my directory tree to:
test.php
foodir
`---- foo.php
---- bardir
`---- bar.php
And then change foo.php to:
include 'bardir/bar.php';
Everything works. It appears that I can include files relative to the currently included file.
However, why am I not able to travel up the directory tree of that file?
Edit:
I know that I can put include 'bardir/bar.php' in foo.php. It would search for bar.php in the location of test.php. However, that doesn't solve my problem if I include foo.php from a file in a directory other than the one where test.php is. That's because in that other directory, bardir/bar.php wouldn't exist.

When you use include 'foodir/foo.php'; that file is now basically running in the "scope" of test.php.
Therefore, the include inside that file include '../bardir/bar.php';
will go up one folder and THEN searching for bardir, which isnt there:
(it's looking for this arrangement:)
parent/test.php
parent/foodir
`---- foo.php
bardir
`---- bar.php
so, the correct include to use inside foo.php would be include 'bardir/bar.php';
in short: If you open test.php all include-paths used in any included file should be relative to the location of test.php - not to their actual location.
ps.: As mentioned in the comments: Includes are first checking the defined include-dir, only if there isn't a match, the path is considered "relative".

Simply do:
include dirname(__DIR__).'/bardir/bar.php';
__DIR__ is the absolute directory path of the file where this constant is used/called (no matter where it's included from), thus __DIR__ is equal to /full/absolute/path/foodir. and dirname(__DIR__) goes one directory up of the path so dirname(__DIR__) /full/absolute/path, and where the bar.php resides is /full/absolute/path/bardir. That's what we want, that's what we get.
This way you don't have to worry include path relativity. It will work any case, no matter where foodir/foo.php is included from

"When you use include it assume the base directory to look for
file is the directory of current file"
So when you have to include file from the another dir you have to specify the relative path from parent directory as here "Base" to include so let say for
Base -> A
->file1.php
->B
->file1.php
we will use
include "../A/file1.php";
for Adding files from A and vice-versa.
Assume ../ as the one level up of specified dir
also you can use __DIR__ like build in constants for getting the dir name of current file

Related

Can't get result with file_exists()

I've been trying to delete a .json file with php on my site, and can't get it to work. It seems I can't get the path to the file right, or it's invisible. So I thought I'd check with file_exists(), and no matter what I try, I cannot get the system to see a file that is on my server.
the json folder exists in this path
/mytheme/assets/js/geofences/1069.json
The php is being run from this path
/mytheme/inc/filelookingforjson.php
I have tried "../assets/js.." to send path pointer up one level using relative path...
I have tried absolute filepaths. and it's behaving like the file isn't there. Is there some htaccess or some other thing i need to do on a wordpress site? Permissions on the geofences folder are set to read, writeable etc... the code below sends me an email saying there is no file. I'm sure I have the path wrong, if i can get this correct than i can work on the unlink... thank you for any input.
$file = '/wp-content/themes/mytheme/assets/js/geofences/1069.json';
if(file_exists($file)){
mail("me#email.com","file exists","file name is there");
} else {me#email.com","file does not exist found","file name is
not there");
}
The issue
If the folder structure is:
mytheme/
inc/
filelookingforjson.php
assets/
js/
geofences/
1069.json
then the path to the json file from the PHP file would be:
../assets/js/geofences/1069.json
However, considering that your PHP file most likely gets included by other PHP files, the path will be relative from the first accessed PHP file.
Why is this?
Imagine this file structure:
index.php
folder/
foo.php
subfolder/
bar.php
assets/
hello.txt
Let's say that you want to read the file hello.txt in the file bar.php, then the relative path to hello.txt would be ../../assets/hello.txt. This would work if you run the file bar.php directly.
The gotcha
The "gotcha" is when you're not accessing bar.php directly.
Let's now say that index.php includes foo.php and foo.php includes bar.php.
If you run index.php, the relative path in bar.php won't work anymore since it isn't relative from the first accessed PHP file in the include chain, which is index.php.
This does make sense if you think of include and require as a "copy/paste". PHP "copys" the code from the included file and "pastes" it into the file that does the including.
Note: this is of course a simplification of how it actually works
Solution
The magic constant __DIR__.
If you add that before your relative path, PHP will replace it with the absolute path to the file it was written in.
The code:
$file = __DIR__ . '/../../assets/hello.txt';
will be read by PHP as:
$file = '/folder/subfolder/../../assets/hello.txt';
Now it won't matter what file includes bar.phpsince the path will stay absolute.
The same thing goes when you're trying to include files using relative paths.
On a real server, the absolute path would probably look something like /path/from/the/file-systems/root/folder/assets/hello.txt.

php included files and directories

Lets say I have two files in directory new_folder: a.php and b.php
In the file of a.php there is a statement:
include_once 'b.php'
In addition, I have a file demo.php in a parent folder, in the demo file there is a statement:
include_once 'new_folder/a.php'
I.E. the folder structure is:
demo.php
new_folder
- a.php
- b.php
Why if I write in the a.php file:
include_once 'b.php' - correct path
include_once './b.php' - incorrect path
include_once 'new_folder/b.php' - incorrect path
Try This
require_once('../b.php');
my answer is based on php.net:
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.
that means that if I write in a.php: include_once 'b.php' ; and then include a.php in demo.php then first it looks for the file in the include_path, then it will look for the file in the directory of the calling script (a.php), and only then it will look for the file in the working directory (that is the directory of the file that we run and starts all the includes- demo.php)
edit: I tried running it and found out that first if there is b.php in the working directory then it will include it and not the b.php from the calling scrip's own directory.
the last check for the file is in the new_folder (the calling script's own directory)

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.

PHP: require doesn't work as it should

I have a directory root:
index.php
includes/
template.php
testfile.php
phpFiles/
processInput.php
testfile.php
index.php:
require_once("includes/template.php");
template.php:
require_once("includes/phpFiles/processInput.php")
processInput.php:
require_once("testfile.php")
require_once("../testfile.php")
This code will work when you run index.php, of course it will not work when you run template.php.
As you can see, index.php includes template.php like normal. But in template.php, you have to include like if you are in the directory that index.php is in. But then, in processInput.php, you include as if you are in the directory that processInput.php is in.
Why is this happening, and how can I fix it so that the include path is always the directory of the file that the require is done in? The second included file have the same include path as the requested file, but the next one does not.
Thanks for your help!
EDIT: The strange thing is that I've included classes in a class folder. And it included other files as it is supposed to, even though the paths are relative. WHY does this happen, and how can I fix it?
VERY IMPORTANT EDIT: I just realized that all this is because in my example, the inclusion in includes/phpFiles/processInput.php includes a file in the same directory: require_once("file in same dir.php"); This is the reason. If you are including a file with out specifying anything more than the filename, the include_path is actually the dir where the file the require is written in is in. Can anyone confirm this?
Use an absolute path.
require_once($_SERVER['DOCUMENT_ROOT']."/includes/phpFiles/processInput.php");
Use a similar form for all your required files and they will work no matter where you are.
You can do this in a few ways, amongst others:
Use set_include_path to control the directories from where to perform require() calls.
Define a common absolute base path in a constant that you define in index.php and use that in every require() statement (e.g. require(BASEPATH . '/includes/template.php')).
Use relative paths everywhere and leverage dirname(__FILE__) or __DIR__ to turn them into absolute paths. For instance: require(__DIR__ . '/phpFiles/processInput.php');
By default, the current working directory is used in the include path; you can verify this by inspecting the output of get_include_path(). However, this is not relative to where the include() is made from; it's relative to the main executing script.
You're using relative paths. You need to use absolute paths: $_SERVER['DOCUMENT_ROOT'].
When you include/require, you are basically temporarily moving all code from one file, to another.
so if file1.php (which is located in root) contains:
require("folder/file.php");
and you include file1.php in file2.php (which is in a different location (say folder directory for example):
file2.php:
require("../file1.php");
Now all of file1.php code is in file2.php. So file2.php will look like this:
require("../file1.php");
require("folder/file.php");//but because file2.php is already in the `folder` directory, this path does not exist...
index.php:
require_once("includes/template.php");
template.php:
require_once("includes/phpFiles/processInput.php")
Your directory structure is off. The file inclusion is being seen from the file you're using it from. So, "template.php" is looking for an "includes/" folder in its current folder (/includes/).
As others are saying, use absolute paths, which will make sure you're always going at it from the file system root, or use:
require_once("phpFiles/processInput.php")
In your template.php file (which is far more likely to break if you ever move things around, which is why others all recommend using absolute paths from the file system root).
BTW, if you're using "index.php" as some kind of framework system, you can consider defining a variable that stores the address of common files such as:
define('APPLICATION_PATH', realpath(dirname(__FILE__));
define('PHPFILES_PATH', APPLICAITON_PATH . '/includes/phpFiles/');

PHP: include file relative to calling file NOT root file?

OK say I have a file called fileA.php in the same directory I have another file called fileB.php
so inside fileA there is this require_once('fileB.php') notice I did not specify a file path because both files are in the same directory.
Now if fileA is included into another file that is located somewhere else, it fails to include fileB because the parent file (the file that included fileA) is not in the same directory as fileB.
So how can I make it so that fileA loads fileB no matter where fileA is included into?
Does that make sense?
Thanks!!
Assuming both fileA.php and fileB.php are guaranteed to be in the same directory, this should work:
// fileA.php
require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR .'fileB.php')
http://php.net/manual/en/function.include.php#78716
You can set the include root to your website root.

Categories