Page 1 of 1

Include-ception

Posted: Tue Jan 10, 2012 2:18 pm
by lenton
I have includes within includes:

first.php

Code: Select all

<?php
echo 'WORKED';
?>
Output: WORKED

dir1/second.php

Code: Select all

<?php
include '../first.php';
?>
Output: WORKED

dir1/dir2/third.php

Code: Select all

<?php
include '../second.php';
?>
Output: Warning: include(../first.php): failed to open stream: No such file or directory in /var/www/test/dir1/second.php on line 2 Warning: include(): Failed opening '../first.php' for inclusion (include_path='.:/usr/share/php:/usr/share/pear') in /var/www/test/dir1/second.php on line 2

dir1/dir2/dir3/forth.php

Code: Select all

<?php
include '../third.php';
?>
Output: Warning: include(../second.php): failed to open stream: No such file or directory in /var/www/test/dir1/dir2/third.php on line 2 Warning: include(): Failed opening '../second.php' for inclusion (include_path='.:/usr/share/php:/usr/share/pear') in /var/www/test/dir1/dir2/third.php on line 2

Why the hell isn't this working?!?

Re: Include-ception

Posted: Tue Jan 10, 2012 3:43 pm
by social_experiment
What happens if you change the include inside banana.php to '../test.php' ?

Re: Include-ception

Posted: Tue Jan 10, 2012 7:29 pm
by lenton
Sorry the previous example wasn't correct, please re-look at my first post.

I just don't understand why it's erroring. :banghead:

Re: Include-ception

Posted: Wed Jan 11, 2012 12:08 am
by social_experiment

Code: Select all

<?php
 #change to
include '/../first.php';
 #change to
include '/../second.php';
?>
I'm guessing that once you include the file it's relative path has to change; i found this on another forum
You can use an include inside an include but keep in mind one thing... The second include is relative to the first, not the top level page.
http://tycoontalk.freelancer.com/php-fo ... to-do.html

Hth

Re: Include-ception

Posted: Wed Jan 11, 2012 7:05 am
by twinedev
The problem is that PHP is going off of the directory that the script was called from. It reads in and processes that file as if all of it's code is in the file where the include is located. So in your "dir1/dir2/third.php" example, it is looking in dir1/dir2 for first.

To see this demonstrated even more, add the following line to each of your three files:

Code: Select all

echo "<p>RUNNING FROM: ",getcwd(),"</p>";
It is good practice to set up some constants to use in your app to always make calls from the root of the website. While there are different methods, the one I usually use is the following:

Every "called" file starts with this:

Code: Select all

<?php
    define('SCRIPT_START', microtime(TRUE);
    require_once($_SERVER['DOCUMENT_ROOT].'/inc/init.inc.php');

    // Rest of code.....
(note, I use "SCRIPT_START' as I have code in my framework that lets me turn on debug mode to track script execution times)

/inc/init.inc.php contains something along the lines of:

Code: Select all

<?php

if (!defined('SCRIPT_START')) { die ('[ERR:'.__LINE__.'] Invalid direct call to file'); }

session_start();

define('DEBUG_MODE', TRUE); // turns on error checking, advanced debugging messages and alerts

if(DEBUG_MODE) { 
    error_reporting(-1);
    // Other settings I do for error handling
}
else {
    error_reporting(0);
    // Other settings I do for error handling
}

// I put this on in case it ends up on a server not set up. sad, but happens
date_default_timezone_set('America/New_York'); 

// These are set so if a cron job runs, there are values in these when they are called 
// (cli = Command Line Interface, just my own label I give)
if (!$_SERVER['HTTP_HOST'] || $_SERVER['HTTP_HOST'] =='') { $_SERVER['HTTP_HOST'] = 'localrun.cli'; }
if (!$_SERVER['REMOTE_ADDR'] || $_SERVER['REMOTE_ADDR'] =='') { $_SERVER['REMOTE_ADDR'] = 'CLI'; }

define ('SYSTEM_NAME',     'Gregs Awesome Script'); 
define ('SYSTEM_EMAIL',    'info@gregsawesomescript.com'); 

define ('STORE_KEY', 'RANDOM_KEY_FOR_THIS_INSTALL_ONLY'); // Used as Key for DB encrypt
define ('SITE_SALT', 'RANDOM_KEY_FOR_THIS_INSTALL_ONLY'); // Used as Salt for PW's

define ('REL_MEDIA_URL',      '/media/');
define ('REL_ADMIN_URL',      '/admin/');

// SSL one set here, so for development can keep it without https:// then change when going live
define ('REG_SITE_URL', 'http://'.$_SERVER['HTTP_HOST']);
define ('SSL_SITE_URL', 'https://'.$_SERVER['HTTP_HOST']);

define ('LOCAL_PATH',            $_SERVER['DOCUMENT_ROOT'].'/');
define ('LOCAL_MEDIA_PATH',      $_SERVER['DOCUMENT_ROOT'].REL_MEDIA_URL);
define ('LOCAL_INC_PATH',        LOCAL_PATH.'inc/');
define ('LOCAL_ADMIN_PATH',      $ _SERVER['DOCUMENT_ROOT'].REL_SITE_ADMIN_URL);

require_once(LOCAL_INC_PATH.'functions.inc.php');

// END-OF-FILE: ~/inc/init.inc.php
This way, now I can do require_once(LOCAL_INC_PATH.'my_file.inc.php'); and it doesn't matter what directory I am in, it will call correctly.
I do the same for image/media:

Code: Select all

<img src="<?php echo REL_MEDIA_URL; ?>my_image.png" alt="my awesome image" />
Other notes: if the file that you need to include is something that the page will not work properly without, you should do require or require_once instead of include or include_once. Include will just give a warning that the file isn't there, require will stop execution.

Also, if it is code that is only needed once, do the require_once over require. Good habit as you get into larger sites to prevent duplicate definition of things.

-Greg