Before I start, this question may have been asked before, but I either don't know what to type to find it specifically and this is a slightly more specific case.
I'm developing a website with many dynamic ties, some of which is at the beginning of every php file there is the line require("global.php"); which does what the name states, among others such as the css file and whatever else is found on the root level. Problem is however, upon entering down into another directory, the link to this file is broken.
Traditionally what I've done (which is an absolutely stupid beginner workaround) is create a variable just before the require called $up which contained the string '../' which recurred respectively depending on how many directories deep the file is from the root. So the line would then appear require($up."global.php");.
I've realised how stupid this is and have tried to find ways around this. One of which is using the variable $_SERVER['DOCUMENT_ROOT'] to print out the root directory but the reason why this won't work 100% is because a) I'm developing the website on a local machine where the 'root' of the website in development is located in a subdirectory on the server and b) it returns the entire path based upon the location on the drive starting from D:\ and working its location that way, which I don't particularly like to work with when it comes to developing websites and would rather remain within the hosted directories of the web server if possible.
So, based on what I've explained, is there an easy way to get the root location of a website (regardless if the project is in a subridectory or the real root of the web server) within a short string that is extremely easy to append to the begining of every file reference in every php file regardless of it's directory level?
Thanks! <3
Suppose you have the following directory:
/srv/website/index.php
/srv/website/lib/functions.php
You could then do this:
define("MY_ROOT", $_SERVER['DOCUMENT_ROOT']);
And use it in every (included) file relatively:
require (MY_ROOT . "lib/functions.php" );
Related
I wrote the PHP code for my website almost 9 years ago. I have a config file called common.php. Each page in my site requires this page to access the site's constants, classes and variables.
I develop on a local machine and then upload files to a live site. The code I have used on my pages to call common.php is:
$main = ($_SERVER['HTTP_HOST'] == 'localhost')? "E:\-=Web=-\-=Sites=-\mysite\main\common.php" :"/home/mysite/public_html/main/common.php";
require_once($main);
This has worked fine and has never given me any issues.
However, I figure I could instead just use:
require_once($_SERVER["DOCUMENT_ROOT"]."/main/common.php")
This would make my code more compact and it also means I do not have to have my development site files always in E://
So my question is, is it good practice to use $_SERVER["DOCUMENT_ROOT"]?
Is this what most developers would do if wishing to call the config file on each page?
The most common and reliable way is to define a constant that contains the path to your code either in your index.php file, or a config.php file which is included from the same directory or a known relative path and reference that:
if (!defined('APP_DIR')) define('APP_DIR', __DIR__); // set the app directory to that of the currently executing file
Your require line for other files then becomes this
require_once(APP_DIR . '/main/common.php');
Now, you can guarantee that this constant will contain what you expect it to. Assuming you've set it right, that is. ;)
Currently our PHP app requires to be set up in the web server's document root (usually by configuring Apache's virtual hosts).
The main reason for that dependency is that our URL-generation logic assumes that all URLs can be accessed through the absolute path /. That makes for easy linking to resources such as images, and pages.
The user may be visiting the app from different sub-folders, so we cannot assume a simple relative path to work.
How would we decouple the app from needing to run in the document root of the web server? Would you suggest parsing $_SERVER['DOCUMENT_ROOT'] in that URL controller to try to decide how far down in the filesystem the file is being accessed? Right now, I don't see a sure-fire way of doing that parsing. Also a complication here is that we use Apache's ReRewrite so URLs don't necessarily match the file system.
I generally use a Simple and Stupid method for this purpose like:
If users can access indeterministically from different entry points of the application, the entry points should know "where they are" relatively to the application root.
First I should know the relative position of my current script w.r. application root so I statically write into the script i.e;
For a script that should be at
...approotdirname/appsubdir1name/appsubdir2name/here.php
.
$relPath = 'approotdirname/appsubdir1name/appsubdir2name';
Note that if your script is at the application root, the $curPath calculated below will be directly your application position on the server.
Second I should learn the current script file path from Php with a uniform format:
$curPath = str_replace('\\','/',dirname(__FILE__));
(str_replace is for replacing \ with / in case they exist.)
In fact a copy of the $relPath (if figured correctly) should exist at the end of the $curPath.
Then I will find the position of $relPath in the $curPath:
$p = stripos($curPath, $relPath, 0);
if(($p === false)||($p < 0)){echo "Relative path: $relPath is invalid."; exit(0);}
Now when we subtract $relPath from $curPath we get where on earth is our application root positioned on the server with a little checking.
$rootPath = ($p > 0)? substr($curPath, 0, $p-1): '/';
I hope this helps.
Please note that restricting user access through a single point like an index.php at application root is generally accepted as a better practice. There at the entry point you can get
$rootPath = str_replace('\\','/',dirname(__FILE__)).'/';
and use it all through your application for file access and includes. As a bonus, you can move your entire application without breaking its file relations.
I see two options:
Refactor the existing program to route all requests through a single script (suggested above, but it's not practical for our project)
Use smudge and clean attribute filters, requiring some relativley advanced git.
Sorry to bother you over something so trivial. I can't word the question properly to get a result on any search bar, I've tried google, and here, but got no related answers.
I'm currently setting up an include statement, and PHP files from different folders need to include the same files, namely "(Top directory)/public_html/Include/Head.php".
I'm not sure how to tell PHP to look for public_html in the top directory. I originally thought that was what ".." was for, but it seems to behave wierdly. Can somone please explain?
Here's what I'm using:
<?php include("../public_html/Include/Head.php") ?>
Also, include is a folder where I put all the files that users generally don't need to view, mainly to get them out of the way, and make my main folder less messy.
Define some global constant: define('TOP_DIR', '/www/') then use that in all your includes:
include(TOP_DIR.'public_html/Include/Head.php');
Put that define() in some easy to reach location and include it on any page you need. This stuff becomes much simpler if you use a framework that always has a single entry point like CodeIgniter. Then you can just have a file of constants and settings you include in your entry point file and you know that those things will always be available.
You could prepend with the doc root so that you have a consistent starting point and won't have to worry about traversing in your particular case, e.g.,
include($_SERVER['DOCUMENT_ROOT'].'/Include/Head.php')
or, for an application-wide solution, you could simply add Include to your include path:
set_include_path(get_include_path() . PATH_SEPARATOR . $_SERVER['DOCUMENT_ROOT'].'/Include');
http://php.net/manual/en/function.set-include-path.php
PHP's file importing is a bit weird, if you want to import relative to the file you want, use this instead:
<?php include(dirname(__FILE__) . "../Include/Head.php") ?>
The reason is that if you have a file in (Top directory)/public_html/myfile.php that includes this file, the relative includes will be relative to myfile.php and not the included file.
There are several things which affect what you're trying to accomplish.
First, absolute and relative paths. Any time you see directory navigation shortcuts in a path, you're working with a relative path. .. means to go up a directory, or to the parent directory.
Second, the concept of rooting or chrooting may apply. Depending on your system, the topmost directory / (or \) may or may not be where you are serving files from. As an example, you can set the topmost folder of a particular web site to be a specific folder in your filesystem (using Apache). This is considered "rooting" the web site to that folder. No user or browser can "see" files from its parent folders.
PHP, however, generally is not rooted to the same location as the web site.
If your PHP files are in multiple levels of folder, yet you need them to all include files from the same location, then you may want to use absolute paths.
The specifics of what your path should be are entirely system dependent.
To keep URLs working in version-controlled projects, I've been using $_SERVER['DOCUMENT_ROOT']. The problem is, I develop projects within a folder, so I get this:
$_SERVER['DOCUMENT_ROOT'] . '/folder/path/to/file.php'
When I go live, I generally simply want the following:
$_SERVER['DOCUMENT_ROOT'] . '/path/to/file.php'
I know there are bigger problems in the world than having to remove and add this folder name, but is there a way I can easily automate this? Can I somehow set my document root locally to include the folder I'm working in? Do I have a fundamental misunderstanding of the way things are working? Kind of new at this stuff, and looking to learn as much as possible and really grok the "why."
Thanks so much!
Instead of using $_SERVER['DOCUMENT_ROOT'], why not declare a constant which always holds the root of your web application?
<?php
define('ABSPATH', dirname(__FILE__));
Put the following code in a file located in the root folder of your application and include it on every page load.
Then, you can simply always do $path = ABSPATH . '/path/to/file.php'; regardless of if your local copy is in a sub-directory folder or not.
If your application already has a file which is included on every page load, you can simply drop the code above in that file and it will work.
Just note that you may have to add additional dirname() calls depending on where that file is located. Add one for each directory you pass from the root of your webapp.
For example, if your webapp is located in /webapp/ and your "global include" is located in /webapp/includes/framework/init.php, then the above code needs to be modified as such:
define('ABSPATH', dirname(dirname(dirname(__FILE__))));
ie.: 2 additional dirname() calls due to two additional folders from the webapp root (includes/framework)
Clarification
The code above is meant to be in one file, and one file only in your web application. That file needs to be included on each page load.
If you already have a file which is included before any processing (such as a configuration file or other), you may copy and paste that code in that file.
The number of dirname() calls depends on how deep the file you copied and pasted the
code in is relative to the root directory of your web application. For the examples above, assume the root of your web application is represented by ~.
If you copy-paste my code into ~/abspath.php, then you need one dirname() call.
If you copy-paste my code into ~/includes/abspath.php, then you need two dirname() calls.
If you copy-paste my code into ~/includes/config/abspath.php, then you need three dirname() calls. Now let's just say that's its final location.
In ~/index.php, you do the following:
<?php
require_once('includes/config/abspath.php');
and you have access to ABSPATH.
In ~/dir/someOtherPage.php you do the following:
<?php
require_once('../includes/config/abspath.php');
and you have access to ABSPATH.
This is why I'm saying that if you already have a file which is included on each page load, its simpler just to drop the above code in it. Just make sure you modify the amount of dirname() calls accordingly. Again, this code is meant to be in ONLY ONE FILE.
declare below line in any of root file (index.php)
$_SESSION["uploads_base_url"]=dirname(__FILE__);
and you can now use this in any of file where uploads needed.
echo $uploads_base_url=$_SESSION["uploads_base_url"];
I have 2 root directories for a site, httpdocs and httpsdocs. I am sure its obvious what the 2 are for. But I want to keep things consistent through-out the site like global navigation. Right now I have two separate files for this (one in each side) and I would like to only have one. This is hard to maintain because each time I change one I have to change the other (if I remember to), it breaks the DRY rule. But if I try to include a file from one side to the other using a relative path it tells me the file path is not allowed because it goes outside the document root. If I try to include it with an absolute URL I get another error saying file access is disabled in the server configuration. (I am on a hosting account so the most I can change as far as server config is limited to .htaccess). So can anyone think of a work-around for this?
Why not put your global include file in yet another directory (lets call it library) and then have each http root have an include file that includes ../library/lib.php, then sets specific paramaters. This gives you the added benifit of your library php files not being in the document root path as well.
And actually. Updating because I just read the entry about "relative path" issues.
Could you set the "include path" php value to include that directory?
Something like this:
ini_set('include_path', realpath(dirname(__FILE__)."/../library").":".ini_get('include_path'));
require_once('lib.php');
Did a little more research - seems that changing open_basedir is not possible unless you are able to edit the httpd.conf or php.ini values. PHP Manual: open_basedir
Do you have the ability to create symbolic links between the two directories?