Properly navigating relative local paths in PHP - php

I'm having trouble specifically with the getimagesize function. I'm making the function call from /item/ajax/image.php relative to the domain's HTTP root. I'm trying to get the dimensions of an image stored at /portfolio/15/image.jpg. From what I understand, the function takes a filename as an argument, so I tried the following:
getimagesize('/portfolio/15/image.jpg')
And
getimagesize('../../portfolio/15/image.jpg')
But both of them just threw PHP errors.

try prefixing below to path:
$_SERVER['DOCUMENT_ROOT']

Relative paths always start from the file that is executed, which is most likely index.php. This is true for included files as well. This means in any file within you project relative paths start from your index.php. (Except a chdir() is done before)
I think it is really bad code to have paths like "../../file.ext" or the like. Define a Constant that has the full path to your application (eg: $_SERVER['DOCUMENT_ROOT']) and prepend it to any path you're using.
Example:
# somewhere in your index.php
define('ROOT_PATH', $_SERVER['DOCUMENT_ROOT']);
# in any included file
$my_path = ROOT_PATH."/portfolio/14/image.jpg"
This is imho the cleanest and most readable way to define paths.

In PHP "/" is not the same as the Apache "/" (web root). In PHP "/" refers to the system root. You should use paths relative to your PHP script location ('portfolio/15/image.jpg' if your script and the 'portfolio' folder are in the same location)

The filename you enter is not related to the http root but should be an existing path in the file system of your web server.
To see what goes wrong you could enter:
realpath('../../portfolio/15/image.jpg')
To see what directory you end up at.
Or use:
imagesize(dirname(__FILE__) . '/../../portfolio/15/image.jpg')
to get the full directory qualification.
As an alternative you can use the web address, but you should specify the full url:
getimagesize('http://yoursite.com/portfolio/15/image.jpg')
However, this is a slower option.

Related

What does the "/" in php require/include mean?

When I use require("/toinclude.php"), what does the "/" mean?
Is it the root dir of my ubuntu?
or is it the www directory apacheset for me?
or is it the path of current file? this seems to be true...
What's more, I really get confused by the use of path in PHP. Is it so that the "/" in require()/include() means the current directory, the "/" in system(...)/exec(...) is
the root directory of Linux, and the "/" in html code <form action="/processpost.php"> is the "www" directory Apache set for me?
In PHP (which is server side), any path that starts with / (at least on Unix-based systems) is the filesystem root. In most (if not all) cases, this is not what you want.
In HTML (which is client side), '/' is the URL root. That is: it is placed directly after the domain name. E.g. /process.php in a HTML file fetched from http://example.com will redirect to http://example.com/process.php. This could be the www-root, but might also be something else depending on settings in the server.
include and require use an include path to get files. If you do not provide a full path (that is, you omit the / at the beginning`), PHP will scan all directories it finds in its include path, starting in the current directory. Often, the path to PEAR modules is in that path, so code like this:
include("SomePearModule/Module.class.php");
works, even though it is not in your website's tree.
More can be found in the documentation.
It's the literal server-side (file system) path. Well, not always literal.
It depends on your server setup. If PHP is running in a jailed chroot, then / as far as PHP sees it might actually be something like /var/web/chroots/domain.com/ or similar.
Most often, you want some kind of configuration file that figures out where libraries and stuff are, based on relative paths of where the script is actually executing, then pass that information to require() and require_once() respectively.
Something like:
<?php
$base = dirname(__FILE__);
$Libraries = $base . '/libraries';
require_once($Libraries . '/Library.php');
?>
If you use any kind of modern framework, this is generally handled for you by whatever means it provides to load things. It's good to just make sure that any calls to require() or require_once() don't have to change depending on where you install the app, it's all relative to where it's executed.

Is it a good idea to use $_SERVER['DOCUMENT_ROOT'] in includes?

Is this, for example, a good idea?
require_once($_SERVER['DOCUMENT_ROOT'].'/include.php');
If you have two virtual hosts on the same server, one for live and one for development, with different Apache DocumentRoots, this would avoid having to include absolute paths when the source of the include is unknown, and may be in any directory.
(Note: file paths in the following section are relative to the web root. They would in fact be like /var/www/app/core/init.php, where /var/www/app is the web root)
For instance: I have an /core/init.php which is called using relative paths from places all over the website (/file.php, /dir/file.php or /dir/dir/file.php).
This init.php then includes several function pages, in the fund directory, a subdir of /core (as in /core/func/userfunctions.php).
So, in init.php, I can use the $_SERVER method, because it breaks if I use a relative path and try to call functions from a page like /dir/file.php.
I can't see any problem with it, but in general what could go wrong?
I've seen cases where $_SERVER['DOCUMENT_ROOT'] is not set or is not what you would expect (i.e. not set in CLI or old IIS, or invalid in certain CGI setups).
For that reason you can use dirname(__FILE__) to obtain the path of the script that line is called in. You can then reference relative paths from there e.g.
include dirname(__FILE__) . '/../../other/file.php';
I go with the above method when the directory structure of the files is known and is not subject to change.
If DOCUMENT_ROOT is not available, the following is a suitable replacement:
substr($_SERVER['SCRIPT_FILENAME'], 0, -strlen($_SERVER['SCRIPT_NAME']));
You don't need to do this. PHP looks for the included file in the document root by default.
You can use set_include_path($new_include_path) to change this behaviour, or edit include_path in the php config file.
Also, from http://php.net/manual/en/reserved.variables.server.php:
'DOCUMENT_ROOT'
The document root directory under which the current script is executing, as defined in the server's configuration file.
For example, if you use URL rewriting, you will be very happy when you find out that the includes in your /there/are/so/many/paths/in/the/url/of/this/ page are still working!

Why do link paths in JavaScript not require a precedding / but paths in PHP includes do?

Sounds nit picky but this had me hung up for about an hour or so.
I have a path set like this in JavaScript
const JAVASCRIPT = 'host/source/ArcJB.js';
which renders in my document like this:
<script type="text/javascript" src="host/source/ArcJ.js"></script>
If I put in a preceding / it breaks the link.
In PHP, for server-side paths I use:
<?php
include_once getcwd() . "/host/source/class.ControlEntry.php";
If I don't put in the / it breaks things.
I guess conceptually how am I suppose to know this so I don't have to pull my hair out with trial and error?
Also noted:
Paths inside my .js file work with either a / or not a / preceding the path.
These are used for image lookup or ajax calls.
You should be aware that the paths you pass to include_once are resolved on the server itself while the paths in Javascript are resolved by the browser. Both basically follow the same rules:
paths starting with / are resolved absolutely. On the server, this is the root directory (i.e. the topmost directory). In the browser, this is basically concatenating the host and the path that you are specifying.
paths not starting with a / are relatively resolved, i.e. against the current directory on the server and against the path in your browser.
Realize that getcwd() returns a directory like /var/www. If you then just concanate host/source/class.ControlEntry.php to it, it will yield /var/wwwhost/source/class.ControlEntry.php. On most (if not, all) PHP SAPI's, you can leave out the getcwd() thing when including a file as the current directory is already being searched when including files. In this case, you do not need the / either.
Finally, the server file paths do not have to match the URLs! http://example.com/script.php can be located at /var/www/script.js. If you refer to /script.php in a HTML file, it will be resolved correctly. On the other hand, you should not try include "/script.php", that will search for a file script.php in the root of your filesystem which is most often not what you are looking for.
Preceding slash is used to denote the path should be considered as an absolute path, which means,
For your Js path, which resides in a HTML file which is parsed by a browser to render its content, it should append what you wrote to the domain to get the file. And if your Js file is located relatively to the current page your snippet is located, the link may break.
For your php file, it is located in a path which can be accessed by following system root to host/source/class.ControlEntry.php
You know where you're files are located. Use relative or absolute paths to them, and it will work both in PHP and JavaScript.
In your examples, the preceding / will make the paths point to somewhere else, breaking the application. In your PHP example, you especially concatenate the path string - it will depend on the evaluation of getcwd().

$_SERVER['DOCUMENT_ROOT'] path not working

I am using document root to provide absolute path which is not working. if i echo this path it turns out to be C:wamp/www/proman/header.php. I i give relative path it works fine what is the problem here?
$path = $_SERVER['DOCUMENT_ROOT']."proman/header.php";
I elaborate my problem here: I have 2 php files data_object.php and user.class.php. user.class.php has an include statement for data_object.php which is relative to user.class.php.These two files are under different directory hierarchy.
Now I have to include this user.class.php in various files (like projects.php, links.php) under different hierarchy when I want to create a User() object. The problem is the relative path for file inclusion of data_object.php does work for say projects.php but if I open links.php the error message says it could not open file data_object.php in user.class.php.
What I think is for relative inclusion of data_object.php it is considering the path of the file in which user.class.php is included.
I am facing such problems in more than one scenarios I have to keep my directory structure the way it is but have to find a way to work with nested includes. I am currently running on a WAMP server but after completion I have to host the solution on a domain. Pls help
Since that's a server variable, you may or may not see it, depending on which web server you're running under (especially IIS), or if something's configured weird.
One way to deal with this problem is to set the variable.
$_SERVER['DOCUMENT_ROOT'] = "C:/some/absolute/path";
// or, if you put this code in a file that's in your document root:
$_SERVER['DOCUMENT_ROOT'] = dirname(__FILE__);
Then, you can either require() this file when you need to verify the document root, or use the auto_prepend_file php.ini option to include the file automatically.
If you are actually trying to make a URL, then you just specify an absolute URL - /proman/header.php, or a relative URL - ../proman/header.php.
In my experience, $_SERVER['DOCUMENT_ROOT'] doesn't including a trailing slash. Try:
$path = $_SERVER['DOCUMENT_ROOT'].'/proman/header.php';

How do I set an absolute include path in PHP?

In HTML, I can find a file starting from the web server's root folder by beginning the filepath with "/". Like:
/images/some_image.jpg
I can put that path in any file in any subdirectory, and it will point to the right image.
With PHP, I tried something similar:
include("/includes/header.php");
...but that doesn't work.
I think that that this page is saying that I can set include_path once and after that, it will be assumed. But I don't quite get the syntax. Both examples start with a period, and it says:
Using a . in the include path allows for relative includes as it means the current directory.
Relative includes are exactly what I don't want.
How do I make sure that all my includes point to the root/includes folder? (Bonus: what if I want to place that folder outside the public directory?)
Clarification
My development files are currently being served by XAMPP/Apache. Does that affect the absolute path? (I'm not sure yet what the production server will be.)
Update
I don't know what my problem was here. The include_path thing I referenced above was exactly what I was looking for, and the syntax isn't really confusing. I just tried it and it works great.
One thing that occurs to me is that some people may have thought that "/some/path" was an "absolute path" because they assumed the OS was Linux. This server is Windows, so an absolute path would have to start with the drive name.
Anyway, problem solved! :)
What I do is put a config.php file in my root directory. This file is included by all PHP files in my project. In that config.php file, I then do the following;
define( 'ROOT_DIR', dirname(__FILE__) );
Then in all files, I know what the root of my project is and can do stuff like this
require_once( ROOT_DIR.'/include/functions.php' );
Sorry, no bonus points for getting outside of the public directory ;) This also has the unfortunate side affect that you still need a relative path for finding config.php, but it makes the rest of your includes much easier.
One strategy
I don't know if this is the best way, but it has worked for me.
$root = $_SERVER['DOCUMENT_ROOT'];
include($root."/path/to/file.php");
The include_path setting works like $PATH in unix (there is a similar setting in Windows too).It contains multiple directory names, seperated by colons (:). When you include or require a file, these directories are searched in order, until a match is found or all directories are searched.
So, to make sure that your application always includes from your path if the file exists there, simply put your include dir first in the list of directories.
ini_set("include_path", "/your_include_path:".ini_get("include_path"));
This way, your include directory is searched first, and then the original search path (by default the current directory, and then PEAR). If you have no problem modifying include_path, then this is the solution for you.
There is nothing in include/require that prohibits you from using absolute an path.
so your example
include('/includes/header.php');
should work just fine. Assuming the path and file are corect and have the correct permissions set.
(and thereby allow you to include whatever file you like, in- or outside your document root)
This behaviour is however considered to be a possible security risk. Therefore, the system administrator can set the open_basedir directive.
This directive configures where you can include/require your files from and it might just be your problem.
Some control panels (plesk for example) set this directive to be the same as the document root by default.
as for the '.' syntax:
/home/username/public_html <- absolute path
public_html <- relative path
./public_html <- same as the path above
../username/public_html <- another relative path
However, I usually use a slightly different option:
require_once(__DIR__ . '/Factories/ViewFactory.php');
With this edition, you specify an absolute path, relative to the file that contains the require_once() statement.
Another option is to create a file in the $_SERVER['DOCUMENT_ROOT'] directory with the definition of your absolute path.
For example, if your $_SERVER['DOCUMENT_ROOT'] directory is
C:\wamp\www\
create a file (i.e. my_paths.php) containing this
<?php if(!defined('MY_ABS_PATH')) define('MY_ABS_PATH',$_SERVER['DOCUMENT_ROOT'].'MyProyect/')
Now you only need to include in every file inside your MyProyect folder this file (my_paths.php), so you can user MY_ABS_PATH as an absolute path for MyProject.
Not directly answering your question but something to remember:
When using includes with allow_url_include on in your ini beware that, when accessing sessions from included files, if from a script you include one file using an absolute file reference and then include a second file from on your local server using a url file reference that they have different variable scope and the same session will not be seen from both included files. The original session won't be seen from the url included file.
from: http://us2.php.net/manual/en/function.include.php#84052
hey all...i had a similar problem with my cms system.
i needed a hard path for some security aspects.
think the best way is like rob wrote. for quick an dirty coding
think this works also..:-)
<?php
$path = getcwd();
$myfile = "/test.inc.php";
/*
getcwd () points to:
/usr/srv/apache/htdocs/myworkingdir (as example)
echo ($path.$myfile);
would return...
/usr/srv/apache/htdocs/myworkingdir/test.inc.php
access outside your working directory is not allowed.
*/
includ_once ($path.$myfile);
//some code
?>
nice day
strtok
I follow Wordpress's example on this one. I go and define a root path, normally the document root, and then go define a bunch of other path's along with that (one for each of my class dirs. IE: database, users, html, etc). Often I will define the root path manually instead of relying on a server variable.
Example
if($_SERVER['SERVERNAME'] == "localhost")
{
define("ABS_PATH", "/path/to/upper/most/directory"); // Manual
}
else
{
define("ABS_PATH, dirname(__FILE__));
// This defines the path as the directory of the containing file, normally a config.php
}
// define other paths...
include(ABS_PATH."/mystuff.php");
Thanks - this is one of 2 links that com up if you google for php apache windows absolute path.
As a newbie to intermed PHP developer I didnt understand why absolute paths on apache windopws systems would be c:\xampp\htdocs (apache document root - XAMPP default) instead of /
thus if in http//localhost/myapp/subfolder1/subfolder2/myfile.php I wanted to include a file from http//localhost/myapp
I would need to specify it as:
include("c:\xampp\htdocs\myapp\includeme.php")
or
include("../../includeme.php")
AND NOT
include("/myapp/includeme.php")
I've come up with a single line of code to set at top of my every php script as to compensate:
<?php if(!$root) for($i=count(explode("/",$_SERVER["PHP_SELF"]));$i>2;$i--) $root .= "../"; ?>
By this building $root to bee "../" steps up in hierarchy from wherever the file is placed.
Whenever I want to include with an absolut path the line will be:
<?php include($root."some/include/directory/file.php"); ?>
I don't really like it, seems as an awkward way to solve it, but it seem to work whatever system php runs on and wherever the file is placed, making it system independent.
To reach files outside the web directory add some more ../ after $root, e.g. $root."../external/file.txt".

Categories