This question has been asked over and over but I could not find the correct answer to my problem... As a little background note, all the code was working perfectly before we moved the class file from /application/lib/class to /library/class ...
I have tried to play with GDFONTPATH, relative, absolute paths with and without the file extension to no avail. Here is some of the lines we have tried so far:
putenv('GDFONTPATH=' . realpath(dirname(dirname(__FILE__)).DIRECTORY_SEPARATOR.'fonts'));
/*1*/ $FontName = dirname(dirname(__FILE__)).DIRECTORY_SEPARATOR.'fonts'.DIRECTORY_SEPARATOR.basename($FontName,'.ttf');
/*2*/ $FontName = '\pChart\fonts\\'.basename($FontName);
/*3*/ $FontName =basename($FontName);
$coords = imagettfbbox($FontSize, 0, $FontName, $Text);
Multiple combination of those tries have also been used to no avail. I am really annoyed by this problem as the #1, when echo'ed gives a full path that opens up the correct font file if copy/pasted in win explorer.
It might help to know the absolute path of the file getting the error and the path of the fontname...
C:\wamp\www\application_bundle\Library\pChart\class\pImage.class.php
C:\wamp\www\application_bundle\Library\pChart\fonts\arialuni.ttf
We are experiencing this problem on all dev platforms (Win, Mac and Linux) PHP 5.3.13
Thank you for your assistance.
Edit: It seems as if the file is not found / the server is not looking at the right folder... If someone could help troubleshoot the problem by pointing out how to figure out what path GD is trying to open would really help.
We have figured out how to make it work.
To put it short, we were including the class file and then calling the methods to write the text. We were doing something like this:
$classPath = 'pChart/';
include($classPath.'/class/pImage.class.php');
//... inside the pImage.class we passed font like this: $FontName = $classPath.'/fonts/arialuni.ttf';
imagettfbbox($FontSize, 0, $FontName, $Text)
It did not work whatever we did before or after... Until we changed the $classPath to
$classpath = '../library/pChart/';
Note that they are (or should) point exactly to the same folder as the code is executed from a file in library root.
We have tried to find why absolute paths were not working but could not reproduce the bug in an isolated environment so there's something fishy with our architecture.
Thank you for your time everyone.
I know this has been answered and accepted but I didn't see anyone chiming in on why this solution worked and what was incorrect in the first place.
The short description of the problem
The current working directory is established at the point php get's it's hands on the request and all relative paths are resolved based on the current working directory, not the directory of the file that the path is referenced in.
The long description of the problem
Relative paths in php are resolved based on the current working directory.
For testing purposes you can always see what the current working directory is by calling getcwd
This value is initially arrived at on an http request as the directory that contains the file that the web server initially handed off the request to php.
So for example if you go to http://www.mydomain.com/index.php the current working directory will be the same as the document root ($_SERVER["DOCUMENT_ROOT"])
For a CLI request the cwd is the directory you are in when you execute the command. So if I am at /home/orangepill and I run /usr/bin/php /path/to/file.php the cwd will be /home/orangepill.
This causes a problem for relative file references within included files.
Lets take this example.
Client navigates to www.mydomain.com
Apache has index.php set in the DirectoryIndex directive and apache finds an index.php file in the document root. Current working directory is set to the document root.
/index.php contains the line include "library/myclass.php";
$_SERVER["DOCUMENT_ROOT"]."/library/myclass.php" exists and all is good
myclass.php contains the line include("myclass_helper.php"); this resolves to $_SERVER["DOCUMENT_ROOT"]."/myclass_helper.php". (remember relative references resolve relative to the current working directory)
$_SERVER["DOCUMENT_ROOT"]."/myclass_helper.php" doesn't exist its actually in $_SERVER["DOCUMENT_ROOT"]."/library/myclass_helper.php"
You are probably thing but wait... I've experienced different behavior in my scripts when including within an include. The reason for that is the include and require language constructs (along with a couple of other file system commands) try to include relative paths from each of the paths specified in the include path php directive. So in the above example if library directory off of the document root existed within the include paths then everything would work as expected.
A wholesale solution for requiring files relative to the current file is to structure your include paths using the __DIR__ contextual constant. So you would use include __DIR__."/myclass_helper.php"; (include dirname(__FILE__)."/myclass_helper.php in pre PHP 5.3 environments) and at runtime this would effectively convert your relative path to an absolute path based on the location of the file doing the include.
For common include directories I have gotten into the habit of specifying a few commonly used locations for use with relative file system references. for example
define ("APPLICATION_PATH", realpath($_SERVER["DOCUMENT_ROOT"]."/application");
define ("LIBRARY_PATH", realpath($_SERVER["DOCUMENT_ROOT"]."/library");
define ("CONFIG_PATH", APPLICATION_PATH."/etc/";
This gives you a lot of anchor points to include paths relative to.
Have you dumped $FontName before this piece of code to debug its value?
Anyway, if you're already setting GDFONTPATH, you don't need to use any path on $FontName, in this case you could just use the font name (arialuni.ttf or even just arialuni) or at most basename() function as in your #3 example.
Your putenv() call could be just putenv('GDFONTPATH=' . realpath('../fonts')).
Try that to see if it works:
putenv('GDFONTPATH=' . realpath('../fonts'));
$FontName = 'arialuni.ttf'; // note that I'm using font name directly
$coords = imagettfbbox($FontSize, 0, $FontName, $Text);
Update 1
Please, dump your GDFONTPATH and tell me what it prints. Add that after your putenv() call, it will force your code to raise an error with the GDFONTPATH it looked for:
trigger_error(sprint('GDFONTHPATH = %s', getenv('GDFONTPATH')), E_USER_ERROR);
One may also just try to state a link relative to the root directory. I had the same problem ("Invalid file font name", function "...") and fixed it like that in the main file where the pChart is being initialized:
$myPicture->setFontProperties(array("FontName"=>$_SERVER['DOCUMENT_ROOT']."/files/lib/pChart/fonts/verdana.ttf"));
Solved the issue for me.
This line USED to be like that:
$myPicture->setFontProperties(array("FontName"=>"fonts/verdana.ttf"));
which - I don't know why - provoked an error today.
Please note that this solution is not very elegant since it relies on the fact that your pChart folder is actually located at something like
http://myHomepage.com/files/lib
, meaning it does not work with relative directories.
Related
I have a directory/file tree as follows:
index.php
/frame/main_class.php
/frame/func/function_1.php
/frame/func/function_1.php
/cfg/config.php
//index.php
require('frame/main_class.php');
new main_class;
//frame/main_class.php
class main_class{
public function __construct(){
require('func/function_1.php');
require('func/function_2.php');
require('cfg/config.php');
}
}
The weird part is that it works. Maybe it is late and I am having a dumb-moment, but shouldn't "require('cfg/config');" be written "require('../cfg/config.php');" ?
And if it is using the root of index.php, then "require('func/function_1.php');" shouldn't work, right?
I have quadruple checked the remote server thinking that maybe there was a stray file or two... there isn't.
How can the two require statements have a different base path.....?
Does anyone know of a code snippet that could cause this to happen? I am working with some $_SERVER variables but I don't appear to be changing any of them....!?
"Files are included based on the file path given or, if none is given, the include_path specified. If the file isn't found in the include_path, include will finally check in the calling script's own directory and the current working directory before failing." Explicitly saying include dirname(__FILE__) . '/path/to/file.php';avoids this confusion. – DCoder
Link to PHP Manual on "dirname".
The PHP engine will look for the requested files in the current directory, but it will also look for them in the list of paths defined in INCLUDE_PATH. If the include path lists the path from where your script is running then the given code will work. If not then it wont.
For that reason amongst others it's not a good idea to rely on the include path to resolve the path of included files. You should give the full path instead.
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!
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().
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';
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".