Getting require_once in Zend to find files - php

I am new to ZEnd, any help is greatly appreciated
I had various contractors work on my site, and things got a messy, with multiple copies of the same folders in different locations. Now I am going in and trying to clean things up. FUN!!! One of the problem I am having is that the require_once statements in Zend are not finding the files they are looking for. I am having to go in and change the paths as follows. Assume that this is the code found in Zend/Gdata/App/FeedEntryParent.php
Not Working (Can't Find File):
require_once 'Zend/Gdata/App/Extension/Updated.php';
Seems to Work Fine:
require_once '/home/paul13/paul13.com/includes/library/Zend/Gdata/App/Extension/Updated.php';
The problem is that most of the require_once statements are writting like the first one. short of going in and manually editing all of them, is there a way to tell the require statements to look in the indicated directory? '/home/paul13/paul13.com/includes/library/' using php.ini? I tried entering
include_path=".:/home/paulthetutor/paulthetutors.com/includes/library"
in php.ini, but that does not seem to solve the problem.

The title of your question seems to have little to do with the content you've posted.
I had various contractors work on my site...are not finding the files
You've paid contractors to deliver code which doesn't work?
The problem is obviously that the path in the first
No - the problem is that your include paths are not set up correctly. If you're using an include path as a mechanism to avoid typing lots of stuff then you're doing it wrong. Your include path should not include entries pointing inside a directory tree maintained by someone else. Nor should you be changing this structure without a very specific and valid objective.
As a temporary workaround until you fix the include/require statements to what they should have been in the first place, then change your include path - either in php.ini, in httpd.conf, in .htaccess, via an auto-prepend or at the top of every script.
(BTW you're confusing folders with directories)

The folder you mentioned in the question is part of the Zend library. You can check if you have a library folder inside your Zend Framework project and whether it contains the file
'Zend/Gdata/App/Extension/Updated.php'
To include the entire ZF library, use the following code either in your public/index.php or in your Bootstrap.php file.
// Define path to application directory
defined('APPLICATION_PATH')
|| define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
// Define application environment
defined('APPLICATION_ENV')
|| define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production'));
// Ensure library/ is on include_path
set_include_path(implode(PATH_SEPARATOR, array(
realpath(APPLICATION_PATH . '/../library'),
get_include_path(),
)));
And yes, selectively remove the require statements one by one and locally copied versions of library files (after making sure that they do not have updated codes, ofcourse).
You might want to check the default Zend Framework application structure here to compare the folder structures.

Related

Is it prefered to use $_SERVER['DOCUMENT_ROOT'] in the website?

Do you think it is preferred to use $_SERVER['DOCUMENT_ROOT'] in website's include statements? Is it supported everywhere without any problem?
Many frameworks use dirname(__FILE__) to work out the application path based on a known file, usually the index.php
In the Zend Framework, they use the following to define the application path, which is then used everywhere in the app:
define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application');
I personally prefer relative paths: include("../../some/other/path.php") Whenever I create a directory, I know exactly how my directory tree is setup, and it doesn't matter whether there is a document root or anything else available.
Furthermore, there are some cases where $_SERVER['DOCUMENT_ROOT'] may not work (eg, I have seen people have issues with it on IIS).

How do you developers set your paths for templates?

I thought I would ask in case I could do it a better way.
On my local (WAMP) I have all my website in the www folder. ( C:\wamp\www )
Now currently I do this when i include a file:
require_once("".$_SERVER['DOCUMENT_ROOT']."/lib/config.php");
When I am working on local and upload site to a webhost i want to ensure the paths don't breakI
Could someone please tell me if I should be doing it this way?
I want to ensure maximum compatibility; meaning that paths won't break if I, for example, move site from local to whatever web host I decided to use or if I, for example, move from one host to another.
Maybe there is a more bullet proof way of doing it?
The problem with using $_SERVER['DOCUMENT_ROOT'] is that it will break if you move your PHP scripts up or down a directory level. Instead use this:
require_once(dirname(__FILE__) . "/lib/config.php");
__FILE__ is the absolute path of the script. dirname() removes the last path component (the script filename) so you can append other path components to it, like /lib/config.php or /../../lib/config.php or whatever. This will work everywhere.
PHP 5.3 introduced a shorthand for dirname(__FILE__), called __DIR__, but this doesn't work in <5.3.
You should see Include path. For that set_include_path is useful.
What I usually do, is make 1 config file (which might include others) with a few very basic constants:
define('PROJECT_ROOT', dirname(dirname(__FILE__))); // or dirname(__DIR__) for PHP 5.3
define('PROJECT_WEB', $_SERVER['DOCUMENT_ROOT']);
// etc
Al my other files/includes will be based on those very simple constants. I will never need relative paths and never the include_path, because both PROJECT_ROOT and PROJECT_WEB are 'real'/absolute.
Other useful (?) constants would be PROJECT_LOGIC and/or PROJECT_CONTROLLERS and/or PROJECT_3RD_PARTY etc.
That works fine for including the config file (although i would get rid of the beginning quotes)
require_once( $_SERVER['DOCUMENT_ROOT'] . "/lib/config.php" );
This is really the only way to do it if you are including the config file from a bunch of different directories.
On bigger project id say that "most" developers have a front controller that all scripts are loaded from. This front controller loads the config file and since its the same file always including the config file there's no need for $_SERVER['DOCUMENT_ROOT'].

Dealing with include and complex directory hierarchy in PHP

I have to deal with complex directories hierarchy, and I am facing the common trouble of include path with PHP.
I have searched the web but I haven't found anything that fit my needs.
For instance, I was using a simple directory hierarchy that never fail: no php script in the site root, only one level of subdirectory, all php script in this sublevel. To include a php file, I was simply using relative path, always starting with '../' just like in this example:
include( '../my_subdirectory/my_script.php' ) ;
This way, I can be sure to locate the file I want...
But there is some drawback:
I can't have more than one level of subdirectory (reason: when a file include a file that include another file, the path used to include the third file is not relative to the path of second file file, but relative to the path of the very first file).
Coming from a C++ background (using handmade makefile), I have always thought it was a dirty way to do it
So I want a way to include file directly from the site root (not the $_SERVER['DOCUMENT_ROOT'] because I may have independant website into subdirectory of this document_root).
I want it to be:
centralized in only one file
portable from a server to another without any change (if possible)
keep php's include simple and elegant, no complex string concat, this should work this way: "include('directory_a/directory_b/my_php_script.php')"
Using a .htaccess that contains:
php_value include_path "/var/www/my_website/"
... do it well except that the path is hardcoded into the .htaccess, annoying for some reason: in my case, I have prod, dev and testing version of the website, and the .htaccess is versionned (it contains many others things). If possible, I want an .htaccess that work everywhere. Something that set the include_path to the path of this current .htaccess would be fine.
So... What is the best practice, dealing with include() and complex directory hierarchy in PHP ?
A good way is to use an absolute path like this :
Php < 5.3 :
include(dirname(__FILE__) . '/yourfile.php');
Php 5.3 :
include(__DIR__. '/yourfile.php');
The __FILE__ constant will always point to the absolute path to the current file.
If you do this in a script in your site root:
define("ROOT_DIRECTORY", dirname(__FILE__));
and include it in every script, you can easily do relative includes:
include ROOT_DIRECTORY."/dir1/dir2/dir3/index.php";
if what you are including are PHP class structures, you may also want to look into Autoloading which is a great feature.
I think the best way to handle this, is to set an "SetEnv directive" in your vhost or httpd.conf for each environment.
httpd.conf:
SetEnv INCLUDES_DIR /var/www/my_website/
In every PHP file, you can use the following $_SERVER variable
include_once($_SERVER['INCLUDES_DIR'].'/my_subdirectory/my_script.php');

How to use a PHP includes across multiple directories/sub directories with relative paths

I'm having difficulty with paths in a cms system I'm attempting to build, I've basically got a folder with my header.php and footer.php files inside.
These are included in index.php and work fine. But then when I attempt to use the same includes in a file within my admin sub directory, the images and CSS are broken, obviously because the relative path is now wrong.
So my question is, how can I overcome this?
After reading some of the other questions on here and various other sources, I think absolute paths are the way forward, but I've always used relative paths, so the various concepts of using config files to specify an absolute path are confusing me.
I usually manage to work things out for myself, but it's been a long day and Im stumped!
i usualy have a file called config in my application root and in it i define a constant for base path and a few others:
define('APP_BASE_PATH', dirname(__FILE__));
define('APP_FUNCTIONS_PATH', APP_BASE_PATH . '/functions');
and i include my files like
include (APP_BASE_PATH . 'includes/another_file.php');
include (APP_FUNCTIONS_PATH . '/function_file.php');
that way i can place my aplication in whatever directory, plus i can move files around without to much worries.
also using full path makes the include faster
I prefer setting the environment variables (in Apache, using .htaccess or the .conf). This way you can move all your files freely anywhere in webroot and it will have access to those variables.
SetEnv lib /library/folder/
SetEnv public /my/web/root/
SetEnv environ DEVELOPMENT
Also you can use the variable named 'environ' mentioned in the above .htaccess snippet to include a server specific file as config file in all of your scripts and set various variables there.
require_once getenv('lib')."Configs/Config_".getenv('environ').".php";
Enjoy your freedom!
or...
include($_SERVER['DOCUMENT_ROOT'] .'/includes/header.php');
Relative and absolute paths in PHP are a bit fragile because they depend not just on the current directory of the including file, but also the current working directory.
So you need a two-part solution.
Firstly, you need a redirector. Basically, this is an include file that serves as a single-point-of-call for all other pages. Its job is to go and include the rest of your infrastructure. All your pages call this redirector and only this redirector (but you can chain them).
This redirector now does
include_once dirname(__FILE__).'/include/include.php';
This lets you change your infrastructure's include file, or location and all you have to update is one file. The dirname() call solves all the relative and absolute problems and has it look for the next step relative to itself. And by definition this only changes when you change it, so it will always work.
The second part is a custom includer so you can call content by name with a function and it goes and gets the right file. Burying this in your infrastructure directory is where is goes. It then becomes a black-box that the pages outside this area call without knowing and without needing to know how it works or where it is. That removes the need for path constants to include page fragments because you have one place doing it all for you.
I have had this similar issue and posted this query in this link in SO. The URL is : Issue with PHP include with global path.
While working on the solutions given by people and looking at various threads (including this one - which I had quoted in my solution at the bottom section of my post), I had a way! I had posted the solution as well. It may help some one who is facing a similar issue.

PHP include file strategy needed

I'm in the process of setting up a php project, but am not very familiar with how to properly use php's include/require commands. My layout currently looks like this:
/public --apache points into this directory
/public/index.php
/public/blah/page.php
/utils/util1.php -- useful classes/code are stored in other directories out here
/dbaccess/db1.php
dbaccess/db1.php
require '../utils/util1.php
public/index.php
require '../dbaccess/db1.php'
public/blah/page.php
require '../../dbaccess/db1.php'
The problem is this from the php 'include' documentation:
If filename begins with ./ or ../, it is looked only in the current working directory
So public/blah/page.php fails because it includes dbaccess/db1.php which blows up when it tries to include util1.php. It fails because it's relative path is from the original script in public/blah/, not from dbaccess/
This seems pretty stupid -- db1.php has to just know where it's being included from which isn't going to work.
I've seen strategies like this:
require_once dirname(__FILE__) . '/../utils/util1.php');
That apparently works since now the path is an absolute path, but just seems really bizarre to me.
Is that normal? Should I continue down that path or am I missing something obvious here?
Usually, the standard conventions are thus: like #grepsedawk said, you'll want to define a constant that contains the root of your project folder and if you can the root of your includes folder:
define('APP_ROOT', dirname(__FILE__));
define('INCLUDE_ROOT', APP_ROOT . "/includes");
Note: the constant name needs to be a string!
Also, you'll notice I'm using dirname(__FILE__);. If you place your constants definition file in a subdirectory, you can do a dirname(dirname(__FILE__));, which is the equivalent of a ../.
Now some other caveats. While PATH_SEPARATOR is a cool constant, it is not needed. Windows accepts / or \ in path names, and since Linux only users / as a path separator, go ahead and always use a / instead of mucking up your code with repeated references to PATH_SEPARATOR.
Now that you have your root constants defined, what you'll do when you need a configuration file included is a simple:
include INCLUDE_ROOT . '/path/to/some/file.php';
You'll probably want your constant definitions (the define(...)'s above) in a bootstrap script in your root directory:
www_root/
index.php
bootstrap.php
The bootstrap will contain the defines (or an include of the constants file), as well as an include of any files that will be required by EVERY page.
And finally the last standard convention you may not use, but if you start doing object oriented programming, the most common method (the PEAR standard) is to name your classes by using an _ to separate namespaces:
class GlobalNamespace_Namespace_Class
//...
And then organizing your file structure mapping name spaces to subdirectories (literally replacing all _'s with /'s):
include_dir/
GlobalNamespace/
Namespace/
Class.php
And using __autoload() functions to load your classes, but that's another question.
Have a configuration script that sets the "INSTALL ROOT" of your project and then use absolute paths. Relative path with multiple includes is a headache in php.
DEFINE("INSTALL_ROOT", "/path/to/www/project")
require_once(INSTALL_ROOT . '/util1.php')
in my config / setup file, i do something like
define('MYAPP_BASEDIR',realpath('.'));
then i reference everything relative to that.
... if your include directory relates specifically to class files and you are able to name them so that the include file name could be derived from the class, you might like to look into spl_autoload_register().
this latter part isn't a direct answer to your question, but it's very handy if you're doing includes for each class you use.
Keep in mind, it starts in the current working directory and then looks through the include paths. If you want to reference all of your paths from some central root directory (or many) you can add that directory in the php.ini file or you can do it programatically with set_include_path( $path.PATH_SEPERATOR.get_include_path());
I suggest an abstraction strategy.
In your application page area, have a single file that all pages include.
This "local" include file has one job: find the include file that is outside the application page area. It then includes that. It can probably be as simple as <?php include dirname(__FILE__).'/../include/include.php/'; ?>
This second file is the single entry point into your library structure. It, or something else it includes, has the job of finding where everything is and including it.
This structure means you have just one file as your library's entry point and how it finds the rest of the library is not the application pages' problem. It also means you have just one file in your application area which knows how to find your library's entry point.
If you need a way for different application pages to load different things, I would suggest a modularisation approach. This can either be a global array you set before the master include, or a function you can call to request libraries by name. Yes, this is a slightly fancier way of your master library file declaring a constant of where everything is -- but it removes the temptation of doing include LIBRARY_DIR.'/utils/util.php'; which straightaway makes it unnecessarily difficult to move util.php out of utils and into misc/util at a later date.
The other advantage of the chained files is that it is then much easier to make your codebase relocatable, which makes it possible for multiple versions to be runnable. And it makes it possible to have one tree for the application and another for your library. Which means another application could use your library. In fact, you could extend the chaining a bit more if you want to help with the isolation further.
You're right, your scripts doesn't have to know the physical path where your includes are.
IMO the location where the includes are should be configured in the PHP.INI file (or .htaccess if you preffer).
Suponse your includes (utils and database are stored here /home/scott/php_includes/).
PHP.INI:
include_path=.:/home/scott/php_includes/
Now your scripts can include the libraries in this way:
dbaccess/db1.php:
require_once 'utils/util1.php';
public/index.php
require_once 'dbaccess/db1.php';
public/blah/page.php:
require_once 'dbaccess/db1.php';
A lot of people have provided good solutions, but I've just got one performance-related remark while talking about includes and requires.
If you start include'ing and require'ing a lot of files, it can be tempting to use include_once or require_once. Cachegrinds of scripts that use a lot of _once's have shown that they really slow down performance as the script has to stop what its doing to scan and make sure the file hasn't been included already. Eliminating as many of the _once's as you can will help a lot.
There was perfect solution - pecl extension called "pwee" - it allowed user define his/her own extern superglobal constants / variable using XML file. Thus you were able to use absolute path as I recomend in such form:
require_once APP_ROOT."/path/to/your/script.php";
The advantage of such solution was:
accessible from everywhere
no server load - everything in server memory
The XML file contained
<Environments>
<Application name="www.domain.com" namespace="">
<Constants>
<Constant name="APP_ROOT" value="/full/path/to/project/source" />
</Constants>
<Constants>
<Constant name="WEB_ROOT" value="/full/path/to/project/public" />
</Constants>
</Application>
</Environments>
link to pwee project
You should distinguish these cases of inclusion:
standalone library - all includes should be relative - to let user integrate it to his/her project easily
executable scripts in your public directory - contain absolute includes to project files and to standalone libraries public files (which has relative includes inside - transparent to user). Using the APP_ROOT constant is elegant way.
a,link,script, form html elemets and header forwards should use relative path when diving into tree hierarchy and absolute path when using common files from higher levels of hierarchy
In case of relative path use this form:
require_once "./relative/path/to/script.php";
Why do I use past tense? Because the project is not more supported - works only with Php4. If anyone knows similar solution with support, please let me know.
The best way to do that is to build flexible autoload system.
Simple map of classnames and proprietary patches. Then any internal require_* or include_* is not needed.
There is of course matter of relative/absolute path for autoloader. Well, absolute is most system-efficient, so in the array I mentioned before u can prepend some kind of variable {I have used Phing-style variable} e.g.
<map>
<path classname="MyClass">${project_directory}/libs/my_classes/MyClass.php</path>
<path classname="OtherClass">${project_directory}/libs/some_new/Other.php</path>
<!-- its so flexible that even external libraries fit in -->
<path classname="Propel">${project_directory}/vendors/propel/Propel.php</path>
<!-- etc -->
</map>
This is xml (think about ini or yaml as well) file and requires compile to php during first start, but after that any path is absolute.
Oh, as you can see no file naming convention or file layout is mandatory - its huge advantage.
Cheers, Alan.
It seems that every time I move my simple scripts from one server to another I have to redefine where things are.
I set up a test environment at home, built a few things, and deployed them to a shared host. The result was that the $_server['DOCUMENT_ROOT'] was two folders higher than the public_html folder on one server, and on another server it was one folder higher.
That skewed all my references. So I tried $_server['WEB_ROOT'] and failed again. I was thinking that the web root was a reference to the root of publicly-accessible folders on the server, but I was wrong.
I have one to throw in the pile that did something really simple without adding a lot of code I don't understand (I don't understand a lot of this code either, I just kept adding as I read rules and got it to work).
This gave me a reference to the publicly-accessible web root on all three servers I tried it on. Now I can move my folder anywhere and it just works, no config file necessary!
pub-doc-root.php:
<?php
//You only need to paste the following line into your script once,
//and it must come before you reference the public document root of your website.
//Use $pubroot.'/path_from_public_document_root_to_file/filename.php
$pubroot = (str_replace(($_SERVER['PHP_SELF']), '', (str_replace('\\', '/', (realpath(basename(getenv("SCRIPT_NAME"))))))));
//uncomment the next line to show the calculated public document root
//relative to the document root.
//echo ("$pubroot");
?>
My test environment:
php 5.3.1
Apache 2.2.14 (Win32) mod_ssl 2.2.14 OpenSSL 0.9.8k
ZendServer-CE-5.0.0GA_RC181-5.3.1-Windows_x86
Why not require it based on it's full path?
For example, /sharedhost/yourdomain.com/apache/www is your document root, so why not use
require('/sharedhost/yourdomain.com/apache/www/dbutils.php');
This also has the advantage of you being able to store your includes outside of your wwwroot so they are far less likely to be inadvertenly exposed via the web.
You could also set up a global variable equal to the /sharedhost/yourdomain.com/apache/ part of it so you can move the site around.
require(WWWROOT . '/dbutils.php');
I use
require '../path/to/file.ext';
without problems.
Also require is a statement not a function so it should be used as
require '/path/to/file.ext';
not
require('/path/to/file.ext');

Categories