I wrote a CMS in PHP. It works fine on most servers but I encountered a strange problem on my latest hosting account. This is either a path problem or a coding problem. The latter seems to be OK as this script works fine on all my other accounts, which is why I'm asking for help.
When I first install my CMS tool I run a script called "inventory.php" in which I attempt to get and display all the directories on the server from the location of my script, which is 2 or 3 directories down from the root, depending on the server. I try to use a global path that goes up to the root and from it to return all the directories it can find. If this file works then the entire CMS works; if not... well that's why I'm here.
Here's the code that scans the directories:
$main_root = realpath('../../');
echo '<b style="color:orange;">All The dirs on this server:</b><hr><br>';
$whats_on_the_server = array_filter(glob($main_root.'/*'), 'is_dir');
foreach($whats_on_the_server as $on_server) {
$on_server = trim($on_server);
if(stristr($on_server,'.')){
$arr1 = preg_split('^/^',$on_server);
echo $arr1[4].'<br>';
}
}
The root is: chroot/home/account/ under which all my folders are located. I can't run a script from that directory, so I must access it from elsewhere. This works fine on other servers but on the one I currently use, it doesn't return anything if the path is set as above. It gets the directory contents if I set the path to a subfolder on the specific server, such as:
$main_root = realpath('../../SomeDir');
I must however get the name of all the directories located on the root.
So probably you don't have the privileges to access the root but do have privilegs to access the given subdirectories?
By the way, you can go to root by simply doing
$main_root = realpath('/');
which is always your most upper path!
You should use:
$main_root = dirname(__FILE__).'../../';
where __FILE__ is a PHP constant for the current file.
Related
I am working on a project with a lot of includes and requires. I don't want to change this everytime I deploy from localhost to my live server.
So I thought to use $_SERVER['DOCUMENT_ROOT'], which worked fine until I checked my git which pushes directly to a backup folder on my live server. It is not in the root, but one level lower.
All the files in this backup folder that use include or require get their files from my server root (public_html/) not the current folder the project is in (public_html/backup/).
So this wouldn't work. After that I tried getcwd();, this fixed above situation but now I can't include files on my localhost.
So now I thought to make a check to see if the file is currently on my local pc or on my live server like this:
$checkpath = getcwd();
$localcheck = 'C:\\';
// Test if path contains C:\
if(strpos($checkpath, $localcheck) !== false){
$absolute_path = $_SERVER['DOCUMENT_ROOT'];
} else{
$absolute_path = getcwd();
}
My only problem is how can I include this for all files when including is my issue?
Maybe there is a better way to get a path that always works no matter if it is live or local?
You can use set_include_path($absolute_path); to change the directory include/require looks from. You would then technically only need to call this once in every PHP request. Beware that you need to provide the actual path to set_include_path. For example, you would need to provide "/home/username/directory" instead of "~/directory".
set_include_path documentation.
/ in the beginning of a link to get to the root folder doesn't work in php include.
for example "/example/example.php"
What is the solution?
I'm assuming by root folder you mean your web document root, rather than filesystem root.
To that end, you can either
add the web root folder to the include path, and include('example/example.php')
or you can include($_SERVER['DOCUMENT_ROOT'].'/example/example.php')
I had this issue too. Paul Dixon's answer is correct, but maybe this will help you understand why:
The issue here is that PHP is a server side language. Where pure HTML documents can access files based on the root url you set up on the server (ie. to access an image from any sub-directory you're on you would use /images/example.jpg to go from the top directory down), PHP actually accesses the server root when you use include (/images/example.jpg)
The site structure that you have set up actually lies within a file system in the Apache Server. My site root looks something like this, starting from the server root and going down:
/home2/siteuserftp/public_html/test/
"test" represents your site root
So to answer your question why your PHP include isn't getting the result you want (it is working exactly as it should) is because you're asking the PHP code to try and find your file at the server root, when it is actually located at the HTML root of your site which would look something like the above.
Your file would be based on the site root of "test/" and would look something like this:
/home2/siteuserftp/public_html/test/about/index.php
The answer Paul Dixon provided:
include($_SERVER['DOCUMENT_ROOT'].'/example/example.php')
is exactly what will fix your problem (don't worry about trying to find the document root to replace 'DOCUMENT_ROOT', PHP will do it for you. Just make sure you have 'DOCUMENT_ROOT' literally in there)
EDIT:
More information DOCUMENT_ROOT and other PHP SERVER variables can be found here
include() (and many other functions like require(), fopen(), etc) all work off the local filesystem, not the web root.
So, when you do something like this
include( "/example/example.php" );
You're trying to include from the root of your *nix machine.
And while there are a multitude of ways to approach what you're doing, Paul Dixon's suggestions are probably your best bets.
Every web server has a public_html folder, in which you usually keep your files etc. By using /, you will not get to public_html, instead you direct towards the main (unaccesible) root. So, use $_SERVER['DOCUMENT_ROOT']."/your/locati.on" instead
I solved this on a machine running Windows and IIS with the following:
<?php
$docroot = 'http://www.example.com/';
include ($docroot.'inc-header.php');
?>
If you're on a local dev machine, you can force your domain to point to localhost by adding the following in C:\Windows\System32\drivers\etc\hosts
127.0.0.1 www.example.com
Also, you'll need to enable allow_url_include in php.ini like so
allow_url_include = On
For me, the following trick worked.
I'm using Windows with IIS, so DOCROOT is C:\Inetpub\wwwroot.
do subst of C:\Inetpub\wwwroot to a drive. Let it be W: (WEB contents).
subst W: C:\Inetpub\wwwroot
edit php.ini this way: append W:\ to include_path, change doc_root to W:\
include_path = ".;c:\php\active\includes;W:\"
doc_root = W:\
put subst command into CMD file within Startup folder to make mapping automatically.
Now, both versions allowed:
include '/common/common.inc'; // access to mapped W: root
include 'common/common.inc'; // access to W: within include_path
some versions of PHP may have the delimiter at the end of document root while others may not. As a practical matter you may want to use:
$r = trim(filter_input(INPUT_SERVER, 'DOCUMENT_ROOT', FILTER_SANITIZE_STRING));
if (substr($r, 0, 1) == '/')
{
define("PATCH_SEPARATOR", "/");
}
else
{
define("PATCH_SEPARATOR", "\\");
}
if (substr($r, -1) == PATCH_SEPARATOR)
{
include_once ($r . 'example/example.php');
}
else
{
include_once ($r . PATCH_SEPARATOR . 'example/example.php');
}
maybe it's a bit unconventional
If I have a case like
/var/www/namedir/ <= root
/var/www/namedir/example/example.php <= file to include
-- directory when i need the include --
/var/www/namedir/dir1/page.php
/var/www/namedir/dir1/dirA/page.php
/var/www/namedir/dir1/dirB/page.php
the solution that I use is simple.
get the path before the "Dir1"
something like this
include (substr(dirname(__FILE__),0,strpos(dirname(__FILE__), '/dir1'))."/example/example.php");
I found it usefull id i need to rename the main subdir
for example from
/var/www/namesite/internalDirA/dirToInclude/example.php
/var/www/namesite/internalDirA/dir1/dirA/example.php
/var/www/namesite/internalDirA/dir1/dirB/example.php
TO
/var/www/namesite/dirReserved/dirToInclude/example.php
/var/www/namesite/dirReserved/dir1/dirA/example.php
/var/www/namesite/dirReserved/dir1/dirB/example.php
This answer is not really for the root directory, but one workaround is to use ../ to jump to the parent directory.Of course, you need to know the file structure for this approach though.
For example, you could use:
include('../parent.php');
include('../../grand_parent.php');
I'm creating a .php file that will be uploaded to the root directory of a server. I need that .php file to then figure out the path to the public_html folder or it's equivalent.
I need to do this because I want my .php file to be able to be uploaded to the root and used on any hosting account. Because many hosting companies use different file paths to the public_html folder or even call it something different, I'm trying to figure out how to detect it.
Preferable there is a server variable or easy test to do this. If not, the public_html folder will always contain a particular file so maybe I could search for this particular file and get the path that way. I'm just worried about a filename search being heavy on memory.
The .php file that is being executed is located inside the ROOT directory and needs to locate the public_html folder.
Like this: /home/user/file.php
needs to detect
/home/user/public_html/ or /home/user/var/www/ or /home/user/website.com/html/ etc.
The challenge with this is that a server can have very many public_html's so outside of the context of a request there is no real way to find out what that is.
One thing that you might be able to do to get this information from a php script (if you know the url to get to the host) is to create a php file called docroot.php that looks like this.
<?php
if ($_SERVER["REMOTE_ADDR"] == '127.0.0.1'){
echo $_SERVER["DOCUMENT_ROOT"];
}
Then within your file.php your would do something like
$docRoot = trim(file_get_contents("http://www.mydomain.com/docroot.php"));
This makes the assumption that the server can resolve to itself via the local interface by name.
I found this website which provided me with the only good solution I have found after scouring the web...
$root = preg_replace("!${_SERVER['SCRIPT_NAME']}$!", "", $_SERVER['SCRIPT_FILENAME']);
The way this works is by getting the full path of the file and then removing the relative path of the file from the full path.
Most of my website is in my root directory. And In that directory there is "css", "functions", "images" folder. Everything works fine when I include php files within index.php or any other root file. It includes it fine and executes it fine.
But problem occurres when I made folder "blog". So this is totally new and separate root folder with CMS and its own "root" files. And I try to include css from main root directory or some php files from "functions" folder in main root directory, Everything breaks down. I know I have to include it as ../functions/myfile.com. But this files includes some other files so it just wont work properly and won't be able to include other files properly.
Is there any idea how to fix this problem?
You can get to the root from within each site using $_SERVER['DOCUMENT_ROOT']. For testing ONLY you can echo out the path to make sure it's working, if you do it the right way. You NEVER want to show the local server paths for things like includes and requires.
Site 1
echo $_SERVER['DOCUMENT_ROOT']; //should be '/main_web_folder/';
Includes under site one would be at:
echo $_SERVER['DOCUMENT_ROOT'].'/includes/'; // should be '/main_web_folder/includes/';
Site 2
echo $_SERVER['DOCUMENT_ROOT']; //should be '/main_web_folder/blog/';
The actual code to access includes from site1 inside of site2 you would say:
include($_SERVER['DOCUMENT_ROOT'].'/../includes/file_from_site_1.php');
It will only use the relative path of the file executing the query if you try to access it by excluding the document root and the root slash:
//(not as fool-proof or non-platform specific)
include('../includes/file_from_site_1.php');
Included paths have no place in code on the front end (live) of the site anywhere, and should be secured and used in production environments only.
Additionally for URLs on the site itself you can make them relative to the domain. Browsers will automatically fill in the rest because they know which page they are looking at. So instead of:
<a href='http://www.__domain__name__here__.com/contact/'>Contact</a>
You should use:
<a href='/contact/'>Contact</a>
For good SEO you'll want to make sure that the URLs for the blog do not exist in the other domain, otherwise it may be marked as a duplicate site. With that being said you might also want to add a line to your robots.txt file for ONLY site1:
User-agent: *
Disallow: /blog/
Other possibilities:
Look up your IP address and include this snippet of code:
function is_dev(){
//use the external IP from Google.
//If you're hosting locally it's 127.0.01 unless you've changed it.
$ip_address='xxx.xxx.xxx.xxx';
if ($_SERVER['REMOTE_ADDR']==$ip_address){
return true;
} else {
return false;
}
}
if(is_dev()){
echo $_SERVER['DOCUMENT_ROOT'];
}
Remember if your ISP changes your IP, as in you have a DCHP Dynamic IP, you'll need to change the IP in that file to see the results. I would put that file in an include, then require it on pages for debugging.
If you're okay with modern methods like using the browser console log you could do this instead and view it in the browser's debugging interface:
if(is_dev()){
echo "<script>".PHP_EOL;
echo "console.log('".$_SERVER['DOCUMENT_ROOT']."');".PHP_EOL;
echo "</script>".PHP_EOL;
}
If I understand you correctly, You have two folders, one houses your php script that you want to include into a file that is in another folder?
If this is the case, you just have to follow the trail the right way.
Let's assume your folders are set up like this:
root
includes
php_scripts
script.php
blog
content
index.php
If this is the proposed folder structure, and you are trying to include the "Script.php" file into your "index.php" folder, you need to include it this way:
include("../../../includes/php_scripts/script.php");
The way I do it is visual. I put my mouse pointer on the index.php (looking at the file structure), then every time I go UP a folder, I type another "../" Then you have to make sure you go UP the folder structure ABOVE the folders that you want to start going DOWN into. After that, it's just normal folder hierarchy.
i had the same issue and found a code on https://css-tricks.com/php-include-from-root/ that fixed it
<?php
$path = $_SERVER['DOCUMENT_ROOT'];
$path .= "/common/header.php";
include_once($path);
?>
None of the above answers fixed this issue for me.
I did it as following (Laravel with Ubuntu server):
<?php
$footerFile = '/var/www/website/main/resources/views/emails/elements/emailfooter.blade.php';
include($footerFile);
?>
Try to never use relative paths. Use a generic include where you assign the DocumentRoot server variable to a global variable, and construct absolute paths from there. Alternatively, for larger projects, consider implementing a PSR-0 SPL autoloader.
I want to refer to my website root, or more exactly, to the directory above my script's one.
Let's say my website is example.com/test. I made a installation site which writes a config file. But it shouldn't write it to example.com/test/install/config.php, but to example.com/test/config.php. And the biggest pain in the ** is that I run on Windows (my development PC).
How do I do it?
If you want to get the web-site document root, you can use:
$_SERVER['DOCUMENT_ROOT']
That should work regardless of the operating system and gives you a path on the local file system (so no www.etcetc.).
If you want to get the fully-qualified path of your site root, from that file it is:
$root = realpath(dirname(__FILE__) . '/../../..');
The double-dots work their way up the directory structure, then realpath() is used to turn it into a proper path. So if you want to traverse one less folder up, use two sets of dots rather than three.