Zend Framework 1.11.11 Include Path open_basedir issues - php

I've seen a number of questions on this site regarding this exact issue, but I'm fairly certain that my case is a bit different. I recently upgraded from ZF 1.9.6 to 1.11.11 and since then things stopped working on my production server.
My localhost is running PHP 5.3.8 while the server is running 5.2.11. I am not sure if that has anything to do with it but I figured I would mention it just in case.
When I first upgraded the framework, I was getting a bunch of open_basedir restriction in effect. errors. I resolved that exactly how several others mentioned, by removing the get_include_path() from the call to set_include_path() in the index.php file. As mentioned here.
That fixed the open_basedir errors, but now I'm having issues elsewhere. In several different files for various reasons I am including files via the include and require statements using relative paths.
For example:
require_once 'application/models/MyModel.php';
But now that suddenly doesn't work anymore! I've had to suddenly prepend all those paths with a ./ like so:
require_once './application/models/MyModel.php';
The problem is, there are way too may instances of that to manually go through and find all of them and change it. Rather, I want to figure out why those paths no longer work on the server but continue to work on my localhost.
My inclination is that it has something to do with the fact that I no longer include the get_include_path() part in the set_include_path() in the index.php file but I am not sure.
Can anyone shed some insight? Thanks!

I suspect it has to do with this note about open_basedir:
The restriction specified with open_basedir is a directory name since PHP 5.2.16 and 5.3.4. Previous versions used it as a prefix.
The difference between checking it as a prefix and checking it as a directory would definitely cause problems like this.
A solution might have something to do with this note in the PHP documentation:
Using a . in the include path allows for relative includes as it means the current directory. However, it is more efficient to explicitly use include './file' than having PHP always check the current directory for every include.
So when setting your include path, I think you should modify the example you linked to like this:
set_include_path(
APPLICATION_PATH . './../library' . PATH_SEPARATOR .
APPLICATION_PATH . './../library/Zend'
);
Notice the "." I added before the first forward slash. This should make it relative to the current working directory and stop you from having to make your includes like ./file.
Also, that says this method is less efficient so you can also consider using a tool such as TextCrawler to do find & replace on multiple files.
Additionally, you can include '.' (current directory - or document root) in your include path when setting it. Like so:
set_include_path(APPLICATION_PATH . '../library'
. PATH_SEPARATOR . APPLICATION_PATH . '../library/Zend'
. PATH_SEPARATOR . '.' // <-- notice this!
);

Related

PHP relative path: can I configure it?

tl;dr: How do I make PHP interpret relative paths in include/require statement from the perspective of the current file?
This is yet another question about that old issue in PHP about relative paths. Please bear with me, as I couldn't find any solution for what I am specifically trying to do.
Consider the following directory tree and files:
[www]:
index.php
config.php
[webroot]:
home.php
index.php requires home.php, found inside webroot:
require('webroot/home.php');
home.php requires config.php, found in the parent directory:
require('../config.php');
My problem is that this won't work in my local development environment (Ubuntu 14.04 LTS / 15.10), whereas it runs flawlessly in production. Every mentioned environment is running Apache 2 and PHP 5.
Strangely, this does run locally when I run it inside my Vagrant VM (Ubuntu 12.04 LTS), accessing it from the host machine. But, right now, I cannot run a VM here.
So, why do these environments behave so differently?
This makes me believe that there must be a way to change how PHP interprets relative paths. I am currently working with a 6GB+ PHP project that is written like the example above, and I really need to avoid the amount of effort that it'll take from me to rewrite every include/require statement (using dirname(__FILE__) or so), as well as the git merge conflicts this might cause.
EDIT: I've just remembered I actually had already asked this question here: PHP: include inside included file
The path used to resolve relative URLs like this is configured by the include_path configuration option which has a dedicated function for setting it at runtime: set_include_path.
Note that the set of paths to search may include ., representing the "current working directory", which can be set with chdir and read with getcwd. You may also need to change this to make explicitly relative paths like ./foo.php and ../foo.php to work.
(I was going to recommend you used __DIR__ or $_SERVER['DOCUMENT_ROOT'] instead, but you mention that you don't want to rewrite existing code. I would still recommend to anyone else reading this to make explicit in each include where paths are relative to, to avoid odd bugs and potential security holes with the dynamic base.)
If you want to override existing functionality in place you need to either install an external library or use namespaces. Both are extra work. I'm guessing that installing an extra library probably isn't even an option.
You could try adding the paths to those folders using set_include_path.
Or you could add a global variable and several global functions like below, for all the require and include overloads, but you would still have to do a find/replace through the whole project for instances of include, require, include_once, require_once... and replace them with "include_rel"...
$include_rel_path = '.';
function include_rel($path){
global $include_rel_path;
$my_path = $include_rel_path;
//TODO maybe need to check for drive letters?
if(strpos($path, '/') === 0) { //absolutepath
$include_rel_path = preg_replace('/\/[^\/]*$/','',$path);
include($path);
} else { //relative path
$include_rel_path .= preg_replace('/\/[^\/]*$/','',$path);
include($my_path.'/'.$path);
}
$include_rel_path = $my_path;
}
You have to use auto_prepend_file. if PHP is run as an Apache module then .htaccess file to the path to your config.php file and any PHP file accessed will automatically have the contents of the config file prepended to it.
For .htaccess:
php_value auto_prepend_file /full/path/to/file/config.php
If your server is using CGI then set this directive in your php.ini or Keep in mind this ONLY will work on a server where If PHP is run as a CGI you need to add edit it in your php.ini file or put it inside a .user.ini file just without the php_value part.
auto_prepend_file /full/path/to/file/config.php
In Nginx you could add this line to server configuration inside location ~ \.php$
fastcgi_param PHP_VALUE "auto_prepend_file=/full/path/to/file/config.php";
Let me know if doesn't resolve your problem.
<?php
$path = $_SERVER['DOCUMENT_ROOT'];
$path .= "/Folder/File.php";
include_once($path);
?>
That should do the trick :)
index.php:
chdir('webroot');
require_once('home.php');

Strange issue with PHP include

I am using XAMPP for PHP development, new to this, was previously familiar with WampServer. I have a require_once statement like this
require_once('config.php');
I assumed it would include the file in the current directory, but it is fetching a file from PEAR directory because the path to PEAR is also set in the include_path directive in php.ini.
However if I change the include_path to just '.' which is the current directory, it seems to work fine.
This had worked fine for me before in WampServer, no clue as to what causes this (it has always looked in the current directory before fetching form include paths). Is this a problem with PHP or something to do with XAMPP? And any solutions for this?
Well, you already found the problem: the include path directive is different.
Every include is looked up relative to the include path, the first matching file is used. If you want to explicitly use a file in a specific directory, use an absolute path:
require_once __DIR__ . '/config.php';

How do I include a PHP script from a base path other than the current script?

I have a PHP application I'm trying to include, but it's causing problems because I'm trying to include its files from a subdirectory. For instance, here's the directory structure (more or less) I'm trying to work with:
/site
/scripts
/local
some_script.php
lib_file_a.php
lib_file_b.php
lib_load.php
lib_load.php has an include command for files lib_file_a.php and lib_file_b.php (relative path).
What I want to accomplish is to include lib_load.php from some_script.php, but there's a problem with the way I'm including lib_load.php. At first I tried require('../../../lib_load.php');.
As you would expect I saw the error, "Failed opening required 'C:\xampp\htdocs\site\scripts\local\lib_file_a.php'". As you can see, PHP is trying to include a file that does not exist. I found a Stack Overflow post that told me about using an absolute path (link), but this did not help. I next tried this code:
require(realpath(dirname(__FILE__) . '../../../' . 'lib_load.php'));
However, this time, the same error comes back. What am I doing wrong?
EDIT: I realized that the issue was actually in the library loader, which turned out to be including files based on an absolute path, not a relative path. (I should have read more carefully.) I resolved the issue by changing the path used by the library. This question should be closed if a mod sees this request.
To include lib load
require $_SERVER['DOCUMENT_ROOT'] . '/scripts/lib_load.php';
inside of lib load
require dirname(__FILE__) . '/lib_file_a.php';
if I got your problem right
Try this:
require dirname(__FILE__) . '/../../../lib_load.php');
Or if you're using PHP 5.3 or higher use this instead (it looks nicer):
require __DIR__ . '/../../../lib_load.php');

DOCUMENT_ROOT is not complete, missing domain folder

I have searched many threads so far but cant seem to find a solution. Inside one of my php scripts I am trying to get a server document root but the value I get is not complete, its simply missing the domain folder. I believe it is due to sharing hosting or smth else.
Here is the current way I am using:
$root = realpath($_SERVER["DOCUMENT_ROOT"]);
and the path I get is like:
/home/content/01/0151247/html
although I know it should be like:
/home/content/01/0151247/html/mydomain
I know as I compared it with SCRIPT_NAME and I see the mydomain there in the path.
Hope someone could direct me.
Thank you and sorry for probably asking another thousand time same question over community, I really tried things around from here, nothing helps me so far.
UPDATE
unfortunately I cant not simply use my index file with DIR as it is a wordpress setup and I am working on a separate folder where I am including some wordpress functionality but for that I need a document_root. If that would help.
UPDATE
apparantly the following way resolved my case, maybe it will help someone one day:
realpath($_SERVER["SUBDOMAIN_DOCUMENT_ROOT"]);
basically because of the server setup and domain configured as a subdomain.
Thanks to all who participated.
Prior to PHP 5.3 you can put a file in the directory whose path you want and define a constant:
define('ROOT_DIR', dirname( __FILE__ ));
After 5.3 you can just do:
define('ROOT_DIR', __DIR__);
The idea being that this would be in config.php of some sort that is included every time the application runs.
Magic Constants Docs
UPDATE
In the config file, you can just append the DOCUMENT_ROOT variable:
$_SERVER['DOCUMENT_ROOT'] = $_SERVER['DOCUMENT_ROOT'] . '/mydomain';
And that should take care of it for you.
Old Solution
The DOCUMENT_ROOT is an environment variable set by the server. So if this is on shared hosting, you cannot changed. An alternative is to set your own constant to it, so in a config type file that is included on your pages you can do something like:
define('DOCUMENT_ROOT', $_SERVER['DOCUMENT_ROOT'] . '/mydomain');
And then just use that constant in place of $_SERVER['DOCUMENT_ROOT']. The other option is to contact your host and inquire about it, maybe it was an oversight on their part and they will fix it.
EDIT
Probably using the __DIR__ as others have posted about is the better way, as the DOCUMENT_ROOT can be set to different items and at least with the __DIR__ you should get an accurate directory each time.
Personally, to get the root of a folder in PHP, I use this in the my index file:
define('ROOT', dirname(__FILE__)); // __DIR__ will work under PHP 5.3

Unknown function in PHP Netbeans - how to suppress?

Since I develop on localhost but deploy elsewhere, and since I don't want to have to force my sites to be under a Windows partition's root directory (currently F:\web_dev\htdocs), code like this:
require_once($_SERVER['DOCUMENT_ROOT'] . '/projXY/database/database_common.php');
OdbcExec($sql); // defined in the file above
causes Netbeans to issue a "Warning: unknown function".
Now, I could get round this by using a directory structure like :
F:\project_1
F:\project_2
instead of
F:\web_dev_htdocs\project_1
F:\web_dev_htdocs\project_2
and then using
require_once('/database/database_common.php');
BUT that imposes constraints on where the end-user an install my site.
Simplest by far would be to tell NetBeans which local directory corresponds to $_SERVER['DOCUMENT_ROOT'], but I can't find a configuration option for that. I am sure this is a common problem. Any suggestions?
Update: NetbBeans v7.0.1
Simply add the /path/to/projXY/database/ directory to your project's include path. Netbeans will then pick up the files there and use them as code references.
http://netbeans.org/kb/docs/php/project-setup.html#phpIncludePath
Addendum
Relying on $_SERVER['DOCUMENT_ROOT'] is generally a bad idea. For one, it eliminates the ability to run parts of your application via the console / command line.
You should instead either use configurable, absolute paths to shared libraries or do as in Brandon's answer and use a relative path from __DIR__ (PHP 5.3) or dirname(__FILE__)
Not sure if this is what you are looking for or not, but I commonly use:
require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'file.php');

Categories