php nested include behavior - php

In many places in my code, I do things like:
file1.php:
<?php
include('../file2.php');
file2.php:
<?php
include('anotherdirectory/file3.php');
Depending on the server or settings I try this on, it either sets the relative paths from the "includer" or from the "includee". This is really confusing.
So file1 might try to include "../anotherdirectory/file3.php" or it might try "anotherdirectory/file3.php".
What settings dictate this behavior? I want to have control over this...

In cases when I need to use relative paths I use the following syntax:
include (realpath(dirname(__FILE__)."/another_folder/myfile.php"));

I would recommend using absolute paths. A good way to do this while still being portable is to make a declaration like this in your public_html/index.php:
define('ROOT', dirname(__FILE__));
Then, you can write includes like this which are very easy:
include(ROOT.'/file.php');
Otherwise, PHP checks to see if the file is in the include path as defined by your php.ini. If it's not there, it tries a relative path to the current script. Which is unpredictable and unmaintainable since you may be nestingly including files from different relative locations.
Edit: If you're constantly including a lot of class files, you may want to look into autoloading. It makes everything way simpler if you're programming in an object-oriented style. I have personally never written the word 'include' in my code for a very long time.
Edit 2: You could use the php.ini directive auto_prepend_file to automatically include a one-line file with the definition of ROOT to each one of your scripts.

As someone on the php learning curve, I have found the best way to reference include paths is by absolute location, not relative, by using the built-in $_SERVER superglobal. In my own files I have been using this with success:
include $_SERVER [ 'DOCUMENT_ROOT' ] . '/path_from_root/file_name.php';
This way it doesn't matter where the included file resides relative to my calling file, and I don't have to worry about manually typing in my fully qualified server path. (Maybe obvious..) This will work no matter how nested the include call is, and if / when I move the calling file to a different directory, for example.
You can use this method with include, require, and any other file-related functions that need a path.
On a related note..
$_SERVER [ 'PHP_SELF' ]
will return the path (relative to the root) of the current file. I also use this quite a bit.
$_SERVER has other useful info you may want to check out here:
http://php.net/manual/en/reserved.variables.server.php
Sorry if this is an older thread, I'm new here.
EDIT: You could save this 'DOCUMENT_ROOT' to a variable for use later, but from recent experience I would recommend against it because then you have to worry about variable scope. The include line as written will work every time regardless of current scope.

With get_include_path() you can see, what the server configuration for this is. In most cases it looks like this:
.:/usr/lib/php
This means, the first place php is looking for a included file is the directory of the script that includes another. If it is not present there, php is looking in /usr/php/lib. If you add more paths, php will also look there for a matching file.
If you include a file, which includes another one, the "root" path is the path of the file which included another one at first.

Related

dirname(__FILE__) VS setting global variable to directories

what are the pros and cons of using this :
$globals['server_url'] = dirname(__FILE__);
$globals['mainfiles'] = dirname(__FILE__).'/main';
and the pros and cons of using this :
$globals['server_url'] = '/srv/www/htdocs/somwhere/';
$globals['mainfiles'] = '/srv/www/htdocs/somwhere/main';
And what do you suggest.
by the way: these are set in config.php file which is called by other files as well, to stop directory conflicts when including files we use it like this :
require_once($globals['server_url'].'/test.php');
dirname(__FILE__) or __DIR__ are better than '/srv/www/htdocs/somwhere/' because they will keep working the day you'll move or rename your folders, or you migrate to another server or another OS.
Portability and flexibility are the main words here.
And globals are bad.
The __FILE__ method works fine, but you need to be aware of where the file is. If you move the file to another directory, the value will change and could potentially break anything that depends on it.
On the other hand, hard coding the path will work fine as well, but you'll need to make sure that it is valid if you ever the move the files to a different directory.
The right solution is personal preference. I would probably go with the __FILE__ method (especially if this is code you will be distributing to other servers/users).
Normally, the $_SERVER superglobal is what you would need, in particular $_SERVER['DOCUMENT_ROOT']. Documentation here.
But if you have applications that completely live in separate subtrees of DOCUMENT_ROOT, you could change the include_path, e.g., like this (but you may want to use some parent dir or subdir of __DIR__):
ini_set('include_path', __DIR__);
If you want to keep the default include_path too, it becomes this:
ini_set('include_path', ini_get('include_path').';'.__DIR__);
Once you have set your include_path, your example becomes simply
require_once('test.php');
And of course hardcoding absolute paths in your application makes it hard and error-prone to move it - in full or in part - on the same server or to another server.

PHP, How to set include path

I've been writing:
include('a.php')
include('b.php')
etc. in my script to include to use functions a() and b(). It gets pretty tedious. Is there a way to set a path of a directory and have multiple files there be accessible by a script?
I tried this in my script:
set_include_path('.;C:\xampp\htdocs\myfunctionfolder');
And I set an environmental variable PATH to have this older in there.
I also in modified php.ini to include
include_path = ".;\xampp\php\PEAR;\xampp\htdocs\myfunctionfolder"
If I have many files in there, how do I access these files without having to include each individually? Setting the environmental variable definitely works in the command prompt.
Do I need to do something else for .php files to be accessible collectively under a directory?
Common practice is to have a "common.php" or "includes.php" file that includes the include/include_once calls (for the sake of simplicity). e.g.
root
[lib]
a.php
b.php
includes.php
index.php
Then includes.php contains:
<?php
include_once('a.php');
include_once('b.php');
?>
Then in any script it's a matter of including the includes.php file.
However, to answer your original question, you can only include one file at a time, per call. You can use something like opendir and readdir to iterate over all files in a specific directory and include them as found (automated so-to-speak) or write out each include yourself based on the files you're creating.
Also, all setting the include path does is set a directory to look in when an include call is made. It's not a directory where the files should automatically be loaded (which is the impression I get from your post).
Setting the include_path will not include every file in that directory, it only adds that directory to the list PHP will search when including a file.
Specifies a list of directories where the require(), include(), fopen(), file(), readfile() and file_get_contents() functions look for files.
Source
This would simplify including files in a deep structure or in a completely different section of the filesystem.
include('/var/somewhere/else/foo.php');
With /var/somewhere/else/ added to the php.ini include_path could become
include('foo.php');
Additionally, as others pointed out, there are common practices but you could look into OOPHP and autoloading classes. This will not work for functions that I know of.
Many developers writing object-oriented applications create one PHP source file per-class definition. One of the biggest annoyances is having to write a long list of needed includes at the beginning of each script (one for each class).
In PHP 5, this is no longer necessary. You may define an __autoload function which is automatically called in case you are trying to use a class/interface which hasn't been defined yet. By calling this function the scripting engine is given a last chance to load the class before PHP fails with an error.
PHP's parser is pretty efficient - you'll waste a lot more time loading a ton of individual files instead of one (or a few) more monolithic files. However, if you insist on keeping things segregated like that, you CAN create meta-include files to load sets of individual files, so you'd only include the one single meta-include file, and it does the rest for you:
meta.php:
include('a.php');
include('p.php');
...
include('z.php');
And then you simply do:
<?php
include('meta.php');
in your scripts and you've got all the individual ones loaded for you.
I have a function like this in most of my projects:
function appendToIncludePath($path)
{
ini_set('include_path', ini_get('include_path') . PATH_SEPARATOR . BASE_DIR . $path . DIRECTORY_SEPARATOR);
}
see this question:
How to include() all PHP files from a directory?
Also, in terms of best practices, you can include multiple functions in the same file if they are at all related, and I would also suggest having more descriptive names of your functions and files. For example, if your a() and b() functions both related to validation for example, name your file validation.php and put both functions in there and try to rename them to something that is related to what they do. This will allow you to remember what they do when you start piling up a huge list of functions ;)
include __DIR__ . '/../folder1/folder2/folder3/Target.php';
include __DIR__ . '/../folder1/folder2/Target.php';
It helps you go to any path.
Download latest PHP zip and extract to C drive then download composer and install it, during installation it ask for PHP path so just select extracted PHP path.
As follow below step.
Go to Computer.
Select Advance System Settings.
From system properties select Environmental Varaibles.
In Environmental Varaibles add Path in User Variable for PCNAME
In Environmental Varaibles add Path in System Variables.
Hit OK.
Restart PC.
Win + R type cmd.
type command php -v.
Vola you good to go.
PHP
http://php.net/downloads.php
Composer
https://getcomposer.org/download/

Dealing with include and complex directory hierarchy in PHP

I have to deal with complex directories hierarchy, and I am facing the common trouble of include path with PHP.
I have searched the web but I haven't found anything that fit my needs.
For instance, I was using a simple directory hierarchy that never fail: no php script in the site root, only one level of subdirectory, all php script in this sublevel. To include a php file, I was simply using relative path, always starting with '../' just like in this example:
include( '../my_subdirectory/my_script.php' ) ;
This way, I can be sure to locate the file I want...
But there is some drawback:
I can't have more than one level of subdirectory (reason: when a file include a file that include another file, the path used to include the third file is not relative to the path of second file file, but relative to the path of the very first file).
Coming from a C++ background (using handmade makefile), I have always thought it was a dirty way to do it
So I want a way to include file directly from the site root (not the $_SERVER['DOCUMENT_ROOT'] because I may have independant website into subdirectory of this document_root).
I want it to be:
centralized in only one file
portable from a server to another without any change (if possible)
keep php's include simple and elegant, no complex string concat, this should work this way: "include('directory_a/directory_b/my_php_script.php')"
Using a .htaccess that contains:
php_value include_path "/var/www/my_website/"
... do it well except that the path is hardcoded into the .htaccess, annoying for some reason: in my case, I have prod, dev and testing version of the website, and the .htaccess is versionned (it contains many others things). If possible, I want an .htaccess that work everywhere. Something that set the include_path to the path of this current .htaccess would be fine.
So... What is the best practice, dealing with include() and complex directory hierarchy in PHP ?
A good way is to use an absolute path like this :
Php < 5.3 :
include(dirname(__FILE__) . '/yourfile.php');
Php 5.3 :
include(__DIR__. '/yourfile.php');
The __FILE__ constant will always point to the absolute path to the current file.
If you do this in a script in your site root:
define("ROOT_DIRECTORY", dirname(__FILE__));
and include it in every script, you can easily do relative includes:
include ROOT_DIRECTORY."/dir1/dir2/dir3/index.php";
if what you are including are PHP class structures, you may also want to look into Autoloading which is a great feature.
I think the best way to handle this, is to set an "SetEnv directive" in your vhost or httpd.conf for each environment.
httpd.conf:
SetEnv INCLUDES_DIR /var/www/my_website/
In every PHP file, you can use the following $_SERVER variable
include_once($_SERVER['INCLUDES_DIR'].'/my_subdirectory/my_script.php');

How does one specify pathnames correctly in PHP?

I'm doing a little home computing project in PHP and am creating references like this...
Beer
This seems to pick up the right file. When I do includes, I seem to need a pathname.
include_once ("/var/www/common.php");
I'm sure this can't be right. Perhaps you could tell me what is the best practice for these things so that I can create scripts that aren't tied to a particular pathname (or operating system, come to that) and so that the file selected in the first example is known/can be controlled? Perhaps some settings in php.ini or apache?
Thank you.
You may use relative paths in PHP, too:
include_once './common.php';
This path now is relative to the script, which was intitially called.
If you leave out the dot
include_once 'common.php';
PHP will check all the paths in you include_path and if it doesn't find a file called common.php there, it will try to include common.php relative to the current file.
Many people have the practice of definining a constant like ROOT in the index.php which is used everywere else:
const ROOT = __DIR__; // as of PHP 5.3
define('ROOT', dirname(__FILE__)); // if you don't have PHP 5.3
Actually, you need an absolute path for both.
for the web resources it should start from the web root - /
for the files you need a point where virtual path meets a filesystem one.
$_SERVER['DOCUMENT_ROOT'] is for that purpose.
so
Beer
and
include_once ($_SERVER['DOCUMENT_ROOT']."/common.php");
will work as desired
You can:
Use relative pathnames. The paths should be relative to the directory where the script that is initially executed (unless the directory has been changed explicitly by the script).
Use $_SERVER['DOCUMENT_ROOT'].
The php ini file setting
include_path = var/www/includes
Means that you just forget all that crap about relative and absolute paths.
It matters not a wit where you call include/require.
Even in say:
/var/www/html/example.com/very/long/way/down/index.php
can contain the line;
include 'settings.php' ;
and if settings.php is in /var/www/includes/ then it will be included.
You can override the ini setting in a various places in apache too, even in .htaccess
This of course ties your application to your server settings, which some find unacceptable, but if you are not distributing your stuff, then read up on ini_get and ini_set too.
You can then go on and create natural directories in your include folder, such as /database and keep database settings in there too.

How to use a PHP includes across multiple directories/sub directories with relative paths

I'm having difficulty with paths in a cms system I'm attempting to build, I've basically got a folder with my header.php and footer.php files inside.
These are included in index.php and work fine. But then when I attempt to use the same includes in a file within my admin sub directory, the images and CSS are broken, obviously because the relative path is now wrong.
So my question is, how can I overcome this?
After reading some of the other questions on here and various other sources, I think absolute paths are the way forward, but I've always used relative paths, so the various concepts of using config files to specify an absolute path are confusing me.
I usually manage to work things out for myself, but it's been a long day and Im stumped!
i usualy have a file called config in my application root and in it i define a constant for base path and a few others:
define('APP_BASE_PATH', dirname(__FILE__));
define('APP_FUNCTIONS_PATH', APP_BASE_PATH . '/functions');
and i include my files like
include (APP_BASE_PATH . 'includes/another_file.php');
include (APP_FUNCTIONS_PATH . '/function_file.php');
that way i can place my aplication in whatever directory, plus i can move files around without to much worries.
also using full path makes the include faster
I prefer setting the environment variables (in Apache, using .htaccess or the .conf). This way you can move all your files freely anywhere in webroot and it will have access to those variables.
SetEnv lib /library/folder/
SetEnv public /my/web/root/
SetEnv environ DEVELOPMENT
Also you can use the variable named 'environ' mentioned in the above .htaccess snippet to include a server specific file as config file in all of your scripts and set various variables there.
require_once getenv('lib')."Configs/Config_".getenv('environ').".php";
Enjoy your freedom!
or...
include($_SERVER['DOCUMENT_ROOT'] .'/includes/header.php');
Relative and absolute paths in PHP are a bit fragile because they depend not just on the current directory of the including file, but also the current working directory.
So you need a two-part solution.
Firstly, you need a redirector. Basically, this is an include file that serves as a single-point-of-call for all other pages. Its job is to go and include the rest of your infrastructure. All your pages call this redirector and only this redirector (but you can chain them).
This redirector now does
include_once dirname(__FILE__).'/include/include.php';
This lets you change your infrastructure's include file, or location and all you have to update is one file. The dirname() call solves all the relative and absolute problems and has it look for the next step relative to itself. And by definition this only changes when you change it, so it will always work.
The second part is a custom includer so you can call content by name with a function and it goes and gets the right file. Burying this in your infrastructure directory is where is goes. It then becomes a black-box that the pages outside this area call without knowing and without needing to know how it works or where it is. That removes the need for path constants to include page fragments because you have one place doing it all for you.
I have had this similar issue and posted this query in this link in SO. The URL is : Issue with PHP include with global path.
While working on the solutions given by people and looking at various threads (including this one - which I had quoted in my solution at the bottom section of my post), I had a way! I had posted the solution as well. It may help some one who is facing a similar issue.

Categories