dirname(__FILE__) VS setting global variable to directories - php

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.

Related

How to call a file outside public_html within the domain directory using php

I have a domain that has a subdomain. I want to call a file in the subdomain folder but apparently my subdomain folder is outside the public_html directory. Here is what i tried but nothing is happening.The subdomain folder is subdomain.
<?php
include("subdomain/conn.php") // location of the file in the subdomain
?>
It is usually most helpful to include with an absolute path instead of a relative path. There are two typical ways to approach this. This example will work with the following directory structure, as you did not provide yours:
+var
|+www
|+public_html
-index.php
|+subfolder
|somescript.php
|+subdomain
|conn.php
1) In your index.php file, declare a constant corresponding to the absolute path to the public_html directory
define('APPLICATION_BASE', __DIR__ . DIRECTORY_SEPARATOR);
Then later use this as the prefix for all includes, and append the path relative to there:
include APPLICATION_BASE . '../subdomain/conn.php';
This option works well for most general purposes, allowing you to quickly include most any file relative to the front-controller/index file
2) Alternately, if you are not using a uniform index file and do not have a consistent point of reference reliable enough to always be included, you would apply a similar approach and include based on an absolute path from the file including it. This usually indicates you are lacking good application structure, but for a quick and dirty app or legacy code that was not structured with a definitive single point of access, this is often necessary. In the case where you had to include a file from somescript.php, and did not reliably arrive there from index.php, you would probably do something like this:
include __DIR__ . '/../../subdomain/conn.php';
It should be noted that this works in a pinch, but it is far from optimal, and you should try to massage your application toward the first approach if at all possible. Using a consistent point of entry will save you a lot of guesswork later when debugging, as you will know all files are included based on relevance to a single origin directory, and it will keep error messages and logging a lot cleaner and more readable over time, which in turn will save you a lot of time debugging.
I haven't tried it yet but it should work.
$public_htmlUrl = $_SERVER['DOCUMENT_ROOT'];
$outsideUrl = "../".$public_htmlUrl;
$file = outsideUrl."subdomain/conn.php";
include($file);

How do you developers set your paths for templates?

I thought I would ask in case I could do it a better way.
On my local (WAMP) I have all my website in the www folder. ( C:\wamp\www )
Now currently I do this when i include a file:
require_once("".$_SERVER['DOCUMENT_ROOT']."/lib/config.php");
When I am working on local and upload site to a webhost i want to ensure the paths don't breakI
Could someone please tell me if I should be doing it this way?
I want to ensure maximum compatibility; meaning that paths won't break if I, for example, move site from local to whatever web host I decided to use or if I, for example, move from one host to another.
Maybe there is a more bullet proof way of doing it?
The problem with using $_SERVER['DOCUMENT_ROOT'] is that it will break if you move your PHP scripts up or down a directory level. Instead use this:
require_once(dirname(__FILE__) . "/lib/config.php");
__FILE__ is the absolute path of the script. dirname() removes the last path component (the script filename) so you can append other path components to it, like /lib/config.php or /../../lib/config.php or whatever. This will work everywhere.
PHP 5.3 introduced a shorthand for dirname(__FILE__), called __DIR__, but this doesn't work in <5.3.
You should see Include path. For that set_include_path is useful.
What I usually do, is make 1 config file (which might include others) with a few very basic constants:
define('PROJECT_ROOT', dirname(dirname(__FILE__))); // or dirname(__DIR__) for PHP 5.3
define('PROJECT_WEB', $_SERVER['DOCUMENT_ROOT']);
// etc
Al my other files/includes will be based on those very simple constants. I will never need relative paths and never the include_path, because both PROJECT_ROOT and PROJECT_WEB are 'real'/absolute.
Other useful (?) constants would be PROJECT_LOGIC and/or PROJECT_CONTROLLERS and/or PROJECT_3RD_PARTY etc.
That works fine for including the config file (although i would get rid of the beginning quotes)
require_once( $_SERVER['DOCUMENT_ROOT'] . "/lib/config.php" );
This is really the only way to do it if you are including the config file from a bunch of different directories.
On bigger project id say that "most" developers have a front controller that all scripts are loaded from. This front controller loads the config file and since its the same file always including the config file there's no need for $_SERVER['DOCUMENT_ROOT'].

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.

use absolute or relative path?

in my config.php where i have all constants i set the PATH to a absolute path.
but this means that when i move my application folder i have to change this path.
i wondered if its better to set a relative path, in that way whenever i move my application between production and development folder, i dont have to change it.
how do you guys do when you move between folders?
The best way I've found is to do the following:
define("PATH", realpath(dirname(__FILE__)));
That gives you the directory of the current file. If you do this in your settings/bootstrap/init file, you'll have it available to your application, and it will work for any file system.
__FILE__ is your friend.
define('BASE_PATH', dirname(realpath(__FILE__)));
This will make your scripts more portable.
Include a file like this
include BASE_PATH . 'includes/header.php';
IMO, absolute paths are bad news. Even if you don't plan to move, your hosting provider could move you, like DreamHost recently did to me. I was fine....
But there are 14 references to "path" on their wiki:
http://wiki.dreamhost.com/Server_Moves
I do three things to solve this:
The first is to use paths relative to the current file and include things using dirname(__FILE__).
The second is to use a loader include that all the pages load. This file has one responsibility: to find the include directory, usually via a relative call. So long as this relative relationship stays, it doesn't need changing.
I also like to support custom settings that belong to the installation rather than the codebase. This is done by an include mechanism and overrides a few settings that will be specific for the server the code is on.

Categories