Модераторы: skyboy, MoLeX, Aliance, ksnk
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Правильный Include 
:(
    Опции темы
WolfON
Дата 2.6.2007, 00:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 604
Регистрация: 19.7.2004

Репутация: 6
Всего: 8



Есть структура проекта:
Код

/
  /classes
    class.Test.php
    class.DB.php
  /config
    DB.inc.php
  /tests
    testTest.php
  index.php


Для модульного тестирования я использую пакет PEAR\PHPUnit, чтобы все это добро заработало в конфиг пришлось добавить
Код

include_path = ".;.\;c:\php\pear"


В class.DB.php:
Код

require_once('../config/DB.inc.php');


В class.Test.php:
Код

require_once('class.DB.php');


В testTest.php:
Код

require_once('../classes/class.Test.php');    
require_once('PHPunit/Framework.php');
require_once('PHPUnit/TextUI/TestRunner.php');


в index.php:
Код

require_once('classes\class.Test.php');


роде все просто и очевидно, но после того, как я изменил конфиг php class.Test.php работает вполне себе спокойно, а вот index.php ругается на 
Fatal error: require_once() [function.require]: Failed opening required '../config/DB.conf.php' (include_path='.;.\;c:\php\pear') in E:\Projects\Test\classes\class.Database.php on line 2

E:\Projects\Test в конфиге апача соответствует /test на сервере, а главная папка c:\www

Что-то я тут недопонимаю >_>
PM MAIL ICQ   Вверх
sTa1kEr
Дата 2.6.2007, 00:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: 56
Всего: 146



include()
Цитата

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 ./ or ../, it is looked only in include_path relative to the current working directory.

Я бы рекомендовал использовать абсолютные пути. Если вы придерживаетесь ООП, то могу предложить использовать класс, который я как-то написал, что бы забыть про инклюды как страшный сон.
Код

<?php
 
// Абсолютный путь к корню сайта
if (!defined("AL_ROOT"))
   define("AL_ROOT", "/home/autoload/www");
 
// Путь к каталогу с классами относительно AL_ROOT
if (!defined("AL_CLASSDIR"))
   define("AL_CLASSDIR", "/classes");
 
// Глубина сканирования директорий
if (!defined("AL_LEVEL"))
   define("AL_LEVEL", 5);
 
// Режим отладки
if (!defined("AL_DEBUG"))
   define("AL_DEBUG", true);
 
function __autoload($className)
{
   Autoload::Instance()->LoadClass($className);
}
 
function Debug($msg)
{
   if (AL_DEBUG)
   {
      if (defined("STDOUT"))
      {
         fwrite(STDOUT, $msg);
      }
      else
      {
         echo nl2br($msg);
         flush();
      }
   }
}
 
class Autoload
{
   private static $_thisInstance = null;
 
   private $Pattern = null;
 
   private $ClassMap = null;
 
   private $IsParsed = false;
 
   private function __construct()
   {
      if (!file_exists("classes.map"))
      {
         $this->ClassMap = array(array(), array());
         $this->ParseSources();
         $this->Serialize();
      }
      else
      {
         $this->ClassMap = unserialize(file_get_contents("classes.map"));
      }
   }
 
   public function ParseSources()
   {
      Debug("Start parsing classes.\n");
      ini_set("max_execution_time", 900);
      set_time_limit(900);
      ignore_user_abort();
 
      if ($this->Pattern === null)
      {
         for ($i = 0; $i < AL_LEVEL + 1; $i++)
         {
            $level[$i] = implode("*", array_fill(0, $i + 1, "/"));
         }
         $this->Pattern = "{".implode(",", $level)."}*.php";
      }
 
      Debug("Get list php files.\n");
      foreach (glob(AL_ROOT.AL_CLASSDIR.$this->Pattern, GLOB_BRACE) as $fileName)
      {
         $this->ParseFile(substr($fileName, strlen(AL_ROOT)));
      }
 
      Debug("Parse successfull finished.\n");
      $this->IsParsed = true;
   }
 
   private function Serialize()
   {
      if (count($this->ClassMap[0]) > 0 && count($this->ClassMap[1]) > 0)
      {
         file_put_contents("classes.map", serialize($this->ClassMap));
      }
   }
 
   private function ParseFile($fileName)
   {
      Debug("Parse file $fileName: ");
      $lastModified = filemtime(AL_ROOT.$fileName);
      if (isset($this->ClassMap[1][$fileName]))
      {
         if ($lastModified <= $this->ClassMap[1][$fileName])
         {
            Debug("File not modified.\n");
            return;
         }
         else
         {
            $this->UnsetFile($fileName);
         }
      }
      $source = file_get_contents(AL_ROOT.$fileName);
      $tokens = token_get_all($source);
      while (($token = array_shift($tokens)) !== null)
      {
         if (is_array($token) && ($token[0] == T_CLASS || $token[0] == T_INTERFACE) && $tokens[1][0] == T_STRING)
         {
            if (isset($this->ClassMap[0][$tokens[1][1]]))
            {
               Debug("\nWarning! Class {$tokens[1][1]} alrady declared in {$this->ClassMap[0][$tokens[1][1]]}\n");
            }
            else
            {
               $this->ClassMap[0][$tokens[1][1]] = $fileName;
            }
            Debug("{$tokens[1][1]}; ");
         }
      }
      Debug("\n");
      $this->ClassMap[1][$fileName] = $lastModified;
   }
 
   private function UnsetFile($fileName)
   {
      unset($this->ClassMap[1][$fileName]);
      while(($key = array_search($fileName, $this->ClassMap[0])) !== false)
      {
         unset($this->ClassMap[0][$key]);
      }
      if ($this->IsParsed)
      {
         $this->Serialize();
      }
   }
 
   private function UnsetClass($className)
   {
      $file = $this->ClassMap[0][$className];
      $this->UnsetFile($file);
   }
 
   /**
    * @return Autoload
    */
   public static function Instance()
   {
      if (Autoload::$_thisInstance === null)
      {
         Autoload::$_thisInstance = new Autoload();
      }
      return Autoload::$_thisInstance;
   }
 
   public function LoadClass($className)
   {
      if (isset($this->ClassMap[0][$className]))
      {
         @include_once(AL_ROOT.$this->ClassMap[0][$className]);
         if (!class_exists($className, false) && !interface_exists($className, false))
         {
            $this->UnsetClass($className);
            $this->Serialize();
            $this->LoadClass($className);
         }
      }
      else
      {
         if (!$this->IsParsed)
         {
            $this->ParseSources();
            $this->Serialize();
            $this->LoadClass($className);
         }
      }
   }
}

 ?>

PM MAIL   Вверх
WolfON
Дата 2.6.2007, 13:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 604
Регистрация: 19.7.2004

Репутация: 6
Всего: 8



Цитата
If filename begins with ./ or ../, it is looked only in include_path relative to the current working directory.

Хех, а ларчик просто открывался %)

Как я понял, у вас в коде есть карта классов, которая загружается в память и потом через нее все инклудит - хорошее решение, но мне пока, учитывая размеры этого проекта - такое не надо.
PM MAIL ICQ   Вверх
Golda
Дата 2.6.2007, 14:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 460
Регистрация: 26.3.2007
Где: Ариель, Израиль

Репутация: 20
Всего: 42



WolfON, 
чтобы измбежать проблем с инклюдами, - только абсолютные пути.

include('file.php') => include(dirname(__FILE__) . '/file.php');  и. т.д.

А если существенно еще и require_once или include_once, то лучше еще и realpath(). 

Вполне вероятная ситуация, когда 

Код

require_once('../config/DB.inc.php');
require_once('.DB.inc.php');


будут как раз восприняты, как разные файлы и подключатся дважды. 

Вы не уследите, когда какая-то функция вдруг начнет использоваться не только из web-интерфейса, но и через cli. В общем, абсолютные пути - меньше проблем


--------------------
"For every problem, there exists a simple and elegant solution which is absolutely wrong." -- J. Wagoner, U.C.B. Mathematics
PM MAIL   Вверх
sTa1kEr
Дата 2.6.2007, 15:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: 56
Всего: 146



Цитата(WolfON @  2.6.2007,  13:09 Найти цитируемый пост)
Как я понял, у вас в коде есть карта классов, которая загружается в память и потом через нее все инклудит - хорошее решение, но мне пока, учитывая размеры этого проекта - такое не надо. 

Верно, но эта карта составляется автоматически (путем парсинга скриптов через token_get_all) первый раз и обновляется каждый раз когда не найден нужный класс, по этому прекрасно работает с проектами любых размеров.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "PHP"
Aliance
IZ@TOP
skyboy
SamDark
MoLeX

Новичкам:

  • PHP редакторы собираются и обсуждаются здесь
  • Электронные книги по PHP, документацию можно найти здесь
  • Интерпретатор PHP, полную документацию можно скачать на PHP.NET

Важно:

  • Не брезгуйте пользоваться тегами [code=php]КОД[/code] для повышения читабельности текста/кода.
  • Перед созданием новой темы воспользуйтесь поиском и загляните в FAQ
  • Действия модераторов можно обсудить здесь

Внимание:

  • Темы "ищу скрипт", "подскажите скрипт" и т.п. будут переноситься в форум "Web-технологии"
  • Темы с именами: "Срочно", "помогите", "не знаю как делать" будут УДАЛЯТЬСЯ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0513 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.