I work with PHP on Windows, sience a few days. The whole time I've been indicated include in the following manner:
In index.php file:
require ('include/init.inc');
In the directory "include" I stated:
In init.inc file:
require ("workbench.inc");
But suddenly no longer works. At one time I must also in "init.inc" specify the directory.
Why did it all the time to work, and suddenly no more?
From the PHP documentation:
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 current working directory (CWD) is important when including other files. It can be retrieved by getcwd().
If your directory structure looks like this
rootdir/
include/
init.rc
workbench.rc
index.php
then a require('include/init.rc') will only work if rootdir/ is the CWD or is part of the search path. Likewise, require('init.inc') assumes the CWD is rootdir/include/. Since the current working directory can change, it is idomatic in PHP to use the more robust
// in index.php
require(__DIR__ . '/include/init.rc');
// in workbench.rc
require(__DIR__ . '/init.rc');
Then the require will work independent of the CWD. This works because the magic constant __DIR__ is replaced by the absolute path to the file that contains the constant without a trailing directory separator, for example
in index.php, __DIR__ is D:\path\to\rootdir and
in include/init.rc, __DIR__ is D:\path\to\rootdir\include.
Related
I have the following code (simplified) to add a path to my include paths (to temporarily fix an website with old code).
set_include_path(get_include_path() . PATH_SEPARATOR . '/foo/bar');
I have a settings file /foo/settings/settings.inc.php
Now when I have set the include path and I am in a file /foo/bar/members.php I want to include the settings file. So what the code does is:
include '../settings/settings.inc.php'
I would think that it would get that file now. But it doesn't. When I put the full path in the include it does work. eg: /foo/settings/settings.inc.php but there are a lot of files. And I thought that this would be a work around for that so I don't have to replace every file manually.
I'd say you can't do that:
Files are included based on the file path given or, if none is
given, the include_path specified. [...]
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.
I have included a folder that contains some classes, in my .htaccess file.
Somewhere deeper under public_html I'm including a PHP file from this folder. Works fine, the include_path is in effect.
But if I write something like this:
require_once '../DB.php';
it fails?
This file is just above the included folder, why can't the PHP engine find it?
The relative paths are always interpreted from the current working directory (usually referred to as CWD). With web requests this is usually the file's directory that got the request to handle, but can be changed any time with chdir(), you can check it's current value with getcwd().
If you want your code to be resilient against the cwd, you can use the __DIR__ magic constant or if you are on an ancient php version (before 5.3) the dirname(__FILE__) in your includes, like this:
require_once __DIR__.'/../DB.php';
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.
I have this condition :
a file : /public_html/folderX/test.php has a line : require_once '../functions/sendemail.php'
on the other hand, /public_html/functions/sendemail.php has a line : require_once '../config.php'
config.php loads perfectly in this situation.
the problem occurs when I try to add that functions/sendemail.php on file(s) which not in the folderX, for example :
when I tried to add require_once 'functions/sendemail.php' on public_html/test.php I got this error message :
Warning: require_once(../config-min.php) [function.require-once]: failed to open stream: No such file or directory in public_html/test.php
how to make require_once '../config.php' inside functions/sendemail.php works 'independently' so wherever it's included on any files this 'require_once' problem won't occur anymore.
I tried to change into 'include_once' but still doesn't work.
thanks!
try something like
require_once( dirname(__FILE__).'/../config.php')
Try using __DIR__ to attain the current path of the script.
require_once(__DIR__.'../config.php');
__DIR__ only works on php 5.3
__DIR__
The directory of the file. If used inside an include, the directory of
the included file is returned. This is equivalent to dirname(__FILE__).
This directory name does not have a trailing slash unless it is the root directory.
(Added in PHP 5.3.0.)
I believe the relative path names are biting you here. Relative paths are (to my knowledge) based on the directory of the currently active script. PHP doesn't chdir into a folder when including or requiring files. The best recommendation (in my limited experience) for this kind of thing is to use absolute paths where possible. So something like:
require_once('../config.php');
would become:
require_once('/home/myuser/config.php'); // Or wherever the file really is
The dirname function can help in this situation.
You must understand that PHP changes directory to that of the outermost script. When you use relative paths (e.g. those that begin with ./, ../, or those that do not begin with /), PHP will use the current directory to resolve the relative paths. This causes problem when you copy-paste the include lines in your code. Consider this directory structure:
/index.php
/admin/index.php
/lib/include.php
Assume the two index files contain these lines:
include_once("lib/include.php");
The above line will work when /index.php is called but not when /admin/index.php is called.
The solution is to not copy-paste code, use correct relative file paths in your include calls:
/index.php -> include_once("lib/include.php");
/admin/index.php -> include_once("../lib/include.php");
I have a file
workers/activity/bulk_action.php which includes a file
include('../../classes/aclass.php');
Inside aclass.php it does:
include ('../tcpdf/config/lang/eng.php');
It seems that the include in the second file is using the first files working directory instead of being relative to itself, resulting in an error. How does this work?
You can adapt the second include with:
include (__DIR__.'/../tcpdf/config/lang/eng.php');
The magic constant __DIR__ refers to the current .php file, and by appending the relative path after that, will lead to the correct location.
But it only works since PHP5.3 and you would have to use the dirname(__FILE__) construct instead if you need compatibility to older setups.
You would be way better off by setting a proper value to the include_path and then use paths relative to this directory.
set_include_path(
get_include_path() .
PATH_SEPARATOR .
realpath(__DIR__ . '/your/lib')
);
include 'tcpdf/config/lang/eng.php';
include 'classes/aclass.php';
I also suggest you take a look at autoloading. This will make file includes obsolete.
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.
You can use dirname(__FILE__) to get a path to the directory where the currently executed script resides:
include(dirname(dirname(__FILE__)) . '/tcpdf/config/lang/eng.php');
(since PHP 5.3, you can use __DIR__)
Or, define a constant in the first file that points to the root directory and use it in your includes.