Форум dkLab и Denwer
Здесь общаются Web-разработчики.
Генеральный спонсор:
Хостинг «Джино»

import package аля Java (Programmer)
Author Message
Programmer
Участник форума



Joined: 23 Sep 2005
Posts: 43
Карма: 2
   поощрить/наказать


PostPosted: Tue Nov 15, 2005 7:25 pm (написано за 7 минут 35 секунд)
   Post subject: import package аля Java
Reply with quote

Code (php): скопировать код в буфер обмена
function import ($File)
{
    define (www.php.net/define) ("IMPORT_EXT", ".php");
    if ($File == null)
        die (www.php.net/die) ();
    if (!defined (www.php.net/defined) ("PATH_SEPARATOR"))
        define (www.php.net/define) ("PATH_SEPARATOR", getenv (www.php.net/getenv) ("COMSPEC")? ';' : ':');
    ini_set (www.php.net/ini_set) ("include_path", ini_get (www.php.net/ini_get) ("include_path") . PATH_SEPARATOR . dirname (www.php.net/dirname) (__FILE__) . ((substr (www.php.net/substr) (php_uname (www.php.net/php_uname) (), 0, 7) == 'Windows')? "/" : "\\") . 'src');
    $File = str_replace (www.php.net/str_replace)(".", ((substr (www.php.net/substr) (php_uname (www.php.net/php_uname) (), 0, 7) == 'Windows')? '/' : '\\'), $File);
    if (ereg (www.php.net/ereg) ("^(.*)(\*)$", $File))
    {
        $Classes = array (www.php.net/array) ();
        $open_dir = opendir (www.php.net/opendir) ($Put = str_replace (www.php.net/str_replace) ('*', '', $File));
        while (false !== ($files = readdir (www.php.net/readdir) ($open_dir)))
            if (is_file (www.php.net/is_file) ($Put . $files) && $files{0} != '.')
                $Classes[] = $Put . $files;
        closedir (www.php.net/closedir) ($open_dir);
        $File = $Classes;
        unset (www.php.net/unset) ($open_dir, $Put, $files, $Classes);
    } else {
        $File .= IMPORT_EXT;
    }
    function import_load ($File)
    {
        if (is_array (www.php.net/is_array) ($File))
            foreach($File as $k => $v)
                $File[$k] = import_load ($v);
        else
        {
            if (file_exists (www.php.net/file_exists) ($File))
                require_once ($File);
        }
    }
    import_load ($File);
}
вот такая несложная функция, эмулирующая одноименный инструмент Java.
Употребляется так же, как и в Java.
Примеры:
Code (php): скопировать код в буфер обмена
import ("php.lib.*"); - загружает все бибилиотеки этого package
import ("php.lib.String"); - загружает конкретный класс данного package


Last edited by Programmer on Sun Nov 20, 2005 11:46 am; edited 1 time in total
Back to top
View user's profile Send private message
Владимир Хоменко
Участник форума



Joined: 11 Jun 2004
Posts: 427
Карма: 42
   поощрить/наказать

Location: Николаев, Украина

PostPosted: Wed Nov 16, 2005 1:16 pm (спустя 17 часов 51 минуту; написано за 49 секунд)
   Post subject:
Reply with quote

Ну зачем же так сразу:
Code (php): скопировать код в буфер обмена
if ($File == null) die (www.php.net/die) ();
можно и просто return
Back to top
View user's profile Send private message Send e-mail
Programmer
Участник форума



Joined: 23 Sep 2005
Posts: 43
Карма: 2
   поощрить/наказать


PostPosted: Wed Nov 16, 2005 3:21 pm (спустя 2 часа 4 минуты; написано за 18 минут 29 секунд)
   Post subject:
Reply with quote

ну... или так (-:
немнго поправлю код. первый листинг работает только единожды, так как:
1) константа уже задана
2) внутренняя функция вызывает ошибку
и добавляю несовсем красивую функцию (как и все, вобщем (-: ) обратную первой. я использую ее для вывода имени упаковки вместо адреса файла...
ну, и прокомментировал все.
Code (php): скопировать код в буфер обмена
/**
 * "разделитель" в зависимости от оси
 */

define (www.php.net/define) ("DEL", ((substr (www.php.net/substr) (php_uname (www.php.net/php_uname) (), 0, 7) == 'Windows')? '/' : '\\'));
/**
 * файлы с каким расширением нужно подгружать в случае полного описания импорта
 */

define (www.php.net/define) ("IMPORT_EXT", ".class");
/**
 * Функция import, работающая аналогично одноименному в Java.
 *
 * @param $File - имя "упаквоки" (package), состоящая из имен папок, разделенных символом "."
 *                Программисты Java для удобства в качестве названия package
 *                используют доменные имена их сайтов,
 *                Например, если сайт dklab.ru, то package - ru.dklab.*; соответсвенно
 *                библиотеки расположены по адресу
 *                http://dklab.ru/...(source dir).../ru/dklab/
 * @void
 *
 * Примеры:
 *     import ("ru.dklab.*");          - подгружает все библиотеки в
 *                                       дирректории ../ru/dklab/
 *     import ("ru.dklab.Source");     - подгружает бибилиотеку по адресу
 *                                       ../ru/dklab/Source.class
 *                                      (или с другим расширением, задается в константе IMPORT_EXT)
 */

function import ($File)
{
    if ($File == null)
        return;
    if (!defined (www.php.net/defined) ("PATH_SEPARATOR"))
        define (www.php.net/define) ("PATH_SEPARATOR", getenv (www.php.net/getenv) ("COMSPEC")? ';' : ':');
    ini_set (www.php.net/ini_set) ("include_path", ini_get (www.php.net/ini_get) ("include_path") . PATH_SEPARATOR . dirname (www.php.net/dirname) (__FILE__) . ((substr (www.php.net/substr) (php_uname (www.php.net/php_uname) (), 0, 7) == 'Windows')? "/" : "\\") . 'src');
    $File = str_replace (www.php.net/str_replace)(".", DEL, $File);
    if (ereg (www.php.net/ereg) ("^(.*)(\*)$", $File)) {
        $Classes = array (www.php.net/array) ();
        $open_dir = opendir (www.php.net/opendir) ($Put = str_replace (www.php.net/str_replace) ('*', '', $File));
        while (false !== ($files = readdir (www.php.net/readdir) ($open_dir)))
            if (is_file (www.php.net/is_file) ($Put . $files) && $files{0} != '.')
                $Classes[] = $Put . $files;
        closedir (www.php.net/closedir) ($open_dir);
        $File = $Classes;
        unset (www.php.net/unset) ($open_dir, $Put, $files, $Classes);
    } else {
        $File .= IMPORT_EXT;
    }
    import_load ($File);
}
/**
 * В случае подгрузки всех библиотек выбранного package (ru.dklab.*)
 */

function import_load ($File)
{
    if (is_array (www.php.net/is_array) ($File)) {
        foreach($File as $k => $v) {
            $File[$k] = import_load ($v);
        }
    } else {
        if (file_exists (www.php.net/file_exists) ($File))
            require_once ($File);
    }
}
/**
 * Переводит адрес файла в адрес Package. я использую при "ловле" ошибок try {} catch () {}
 * в классе исключений
 */

function file2package ($arg)
{
    $arg = preg_replace (www.php.net/preg_replace) ("/(.*)src/is", "", $arg);
    // вот он! некрасивый момент...
    $arg{0} = ' ';
    $arg = preg_replace (www.php.net/preg_replace) ("/(\.)(.*)/is", "", trim (www.php.net/trim) ($arg));
    $arg = str_replace (www.php.net/str_replace) (DEL, ".", $arg);
    if ($arg == 'index')
        $arg = '<standart package>';
    return $arg;
}


Last edited by Programmer on Sun Nov 20, 2005 11:51 am; edited 1 time in total
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 412
   поощрить/наказать


PostPosted: Sun Nov 20, 2005 1:27 am (спустя 3 дня 10 часов 5 минут; написано за 2 минуты 50 секунд)
   Post subject:
Reply with quote

А чегой-то у Вас в исходнике отступы так злостно поехали?
С такими отступами - плоховато этому топику в Готовых решаниях...

Кроме того, я не совсем понимаю, зачем же все это. Есть вот такой документ:
pear.php.net/manual/ru/standards.php
Его очень многие разработчики рекомендуют придерживаться, как стандарта де факто. Соответственно, подгрузка библиотек будет просто:

require_once "Ru/Dklab/Class.php";

Конечно, звездочки тут не поддерживаются, это ясно, но - я не встречал пока еще ситуации, когда нужно было грузить прямо ВСЕ файлы одного пакета. Если одни классы требуют других в зависимостях, то в них просто пишется очередной require_once, и все.
Back to top
View user's profile Send private message Send e-mail
Гость1234
Guest





Карма: 388
   поощрить/наказать


PostPosted: Sun Nov 20, 2005 2:31 am (спустя 1 час 4 минуты; написано за 25 секунд)
   Post subject:
Reply with quote

а строчку
define ("DEL", ((substr (php_uname (), 0, 7) == 'Windows')? '/' : '\\'));
можно вообще убрать и использовать DIRECTORY_SEPARATOR
Back to top
Programmer
Участник форума



Joined: 23 Sep 2005
Posts: 43
Карма: 2
   поощрить/наказать


PostPosted: Sun Nov 20, 2005 12:00 pm (спустя 9 часов 28 минут; написано за 3 минуты 39 секунд)
   Post subject:
Reply with quote

Дмитрий Котеров, отступы подправил, документ прочитал (спасибо).
Разместил тему из-за того, что накануне потребовалось подгрудать именно все библиотеки сразу.
Впринципе, это довольно удобно. Особенно, если, например, в упаковке (ru.Dklab.Objects.*) находятся несколько файлов, один из которых - интерфес, остальные - его реализации.
Гость1234, да, Вы правы. А я и не вспомнил о ней.
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 412
   поощрить/наказать


PostPosted: Sun Nov 20, 2005 10:12 pm (спустя 10 часов 12 минут; написано за 1 минуту 7 секунд)
   Post subject:
Reply with quote

Интересно, зачем Вам в программе прямо ВСЕ реализации одного и того же интерфейса... Что, неужели их все будете использовать в одном скрипте? Вы точно уверены, что не пытаетесь бороться таким образом с зависимостями между библиотеками, когда одна библиотека требует другую, а та - третью, и т.д.?
Back to top
View user's profile Send private message Send e-mail
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 268
   поощрить/наказать

Location: Питер

PostPosted: Sun Nov 20, 2005 10:42 pm (спустя 29 минут; написано за 1 минуту 40 секунд)
   Post subject:
Reply with quote

Дмитрий Котеров
На самом деле, для некоторых задач это очень полезное и удачное решение.
У меня подобное реализуется в JS интерфейсе. Таким образом унифицируется название пакета/класса, файла и определение области видимости.

Полностью поддерживаю автора.
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 412
   поощрить/наказать


PostPosted: Sun Nov 20, 2005 11:53 pm (спустя 1 час 11 минут; написано за 1 минуту 11 секунд)
   Post subject:
Reply with quote

Можно еще сделать:

foreach (glob(dirname(__FILE__)."/Ru/Dklab/*.php") as $f) require_once $f;

Это совсем ненамного длиннее... Правда, тут поиск идет не по include_path, а от текущей директории.
Back to top
View user's profile Send private message Send e-mail
Rumata
Профессионал



Joined: 17 Aug 2003
Posts: 1850
Карма: 185
   поощрить/наказать


PostPosted: Mon Nov 21, 2005 11:05 am (спустя 11 часов 12 минут; написано за 4 минуты 15 секунд)
   Post subject:
Reply with quote

личные замечания по коду
1. используйте стандартные коснтанты DIRECTORY_SEPARATOR и PATH_SEPARATOR, которые в основном тексте модуля определяйте при их отсутствии
2. избавьтесь от import_load - она у вас вызывается единожды
3. для подгрузки коллекции файлов используйте glob, opendir/readdir/closedir или встроенный класс Dir

это может быть востребовано для подгрузки нескольких модулей, но не учитывает зависимости и возможный порядок загрузки модулей
Back to top
View user's profile Send private message
Programmer
Участник форума



Joined: 23 Sep 2005
Posts: 43
Карма: 2
   поощрить/наказать


PostPosted: Tue Nov 22, 2005 11:25 am (спустя 1 день 19 минут; написано за 1 минуту 48 секунд)
   Post subject:
Reply with quote

Вот... Посидел, подумал, написал.
Теперь немного лучше, опрятнее (IMHO).
Почти все ваши замечания пересмотрел в коде.
Code (php): скопировать код в буфер обмена
<?php

/**
 * Import.php
 *
 * Created on 21 Ноябрь 2005 г., 23:11
 */


/**
 *
 * @author  Яткевич А. С.
 * @version 1.0
 */


/**
 * Расширение подгружаемых файлов
 */

define (www.php.net/define)("IMPORT_EXT", ".php");

/**
 * Дирректория, предназначенная для хранения библиотек
 */

define (www.php.net/define)("IMPORT_SOURCE_DIR", "src");

/**
 * Разделитель для конфигурации
 */

if (!defined (www.php.net/defined)("PATH_SEPARATOR")) {
    define (www.php.net/define)("PATH_SEPARATOR", getenv (www.php.net/getenv)("COMSPEC")? ';' : ':');
}

/**
 * Путь до файла
 */

if (!defined (www.php.net/defined)("DIRECTORY_SEPARATOR")) {
    define (www.php.net/define)("DIRECTORY_SEPARATOR", ((substr (www.php.net/substr)(php_uname (www.php.net/php_uname)(), 0, 7) == 'Windows')? '/' : '\\'));
}

/**
 * Класс, обеспечивающий подгрузку дополнительных
 * модулей для дальнейшего их использования в коде скрипта.
 * Является примерной копией аналогичного оператора в Java.
 *
 * @package System
 * @author  Александр Яткевич
 * @version 1.0
 * @access  public
 */


class Import
{
    const END_PACK = 1;
    const ALL_PACK = 2;
    const ONE_PACK = 3;

    const NOTEXISTS  = 1;
    const SYNTAX     = 2;

    var $package;
    var $mode;
    var $string;

    /**
     * Конструктор класса.
     * Выполняет все необходимые проверки перед подгрузкой
     * модулей.
     *
     * Параметр package задается при создании объекта.
     *
     * Примеры:
     *     new Import("com.example.*")     -> src/com/example/..
     *     new Import("com.(*)")           -> src/com/example/..
     *                                        src/com/somedir/..
     *                                        src/com/one/two/three/..
     *     new Import("com.example.Class") -> src/com/example/Class.php
     *
     * @param string $package   определяет имя библиотеки или ее
     *                          относительный адрес
     *
     * @void
     *
     * @access public
     */

    function Import($package)
    {
        if ($package == null) {
            return;
        } else {
            if (!is_string (www.php.net/is_string)($package))
                return;
        }
        $this->package = $package;
        self::get_mode();
        self::include_path();
        self::parseSOP();
        self::parse_package();
    }

    /**
     * Определяет адрес для "инклуда" библиотек
     *
     * @void
     *
     * @access private
     */

    function include_path()
    {
        ini_set (www.php.net/ini_set)("include_path", ini_get (www.php.net/ini_get)("include_path") . PATH_SEPARATOR . dirname (www.php.net/dirname)(__FILE__) . DIRECTORY_SEPARATOR . IMPORT_SOURCE_DIR);
    }

    /**
     * В зависимости от типа "упаковки" начинает подгрузку файлов
     *
     * @void
     *
     * @access private
     */

    function parse_package()
    {
        $this->package = str_replace (www.php.net/str_replace)(".", DIRECTORY_SEPARATOR, $this->package);
        switch ($this->mode) {
            case self::END_PACK:
            self::loadSt1();
            break;

            case self::ALL_PACK:
            self::loadSt2();
            break;

            case self::ONE_PACK:
            self::loadSt3();
            break;

        }
    }

    /**
     * @void
     *
     * @access private
     */

    function loadSt1()
    {
        $Classes = array (www.php.net/array) ();
        $open_dir = opendir (www.php.net/opendir)($Put = str_replace (www.php.net/str_replace)('*', '', IMPORT_SOURCE_DIR . DIRECTORY_SEPARATOR . $this->package));
        print (www.php.net/print)("^(.*)" . IMPORT_EXT . "$");
        while (false !== ($files = readdir (www.php.net/readdir)($open_dir))) {
            if (is_file (www.php.net/is_file)($Put . $files) && $files{0} != '.') {
                $Classes[] = $Put . $files;
            }
        }
        closedir (www.php.net/closedir) ($open_dir);
        $this->package = $Classes;
        print_r (www.php.net/print_r)($this->package);
        unset (www.php.net/unset)($open_dir, $Put, $files, $Classes);
        self::import_load($this->package);
    }

    /**
     * @void
     *
     * @access private
     */

    function loadSt2()
    {
        $this->package = str_replace (www.php.net/str_replace)(array (www.php.net/array)("*", "(", ")"), array (www.php.net/array)("", "", ""), $this->package);
        $this->string = "";
        self::recurs_open(IMPORT_SOURCE_DIR . DIRECTORY_SEPARATOR . $this->package);
        $this->package = explode (www.php.net/explode)("|", $this->package);
        print_r (www.php.net/print_r)($this->package);
        self::import_load($this->package);
    }

    /**
     * @void
     *
     * @access private
     */

    function loadSt3()
    {
        $this->package .= IMPORT_EXT;
        self::import_load($this->package);
    }

    /**
     * Разбирает строку описания "упаковки" на правильность
     * написания
     *
     * @void
     *
     * @access private
     */

    function parseSOP()
    {
        if (preg_match (www.php.net/preg_match)("{
                (?:
                    (?<= [-/&+\[\]\<\>\:\;\!])
                )
            }xs"
, $this->package)) {
            self::error(self::SYNTAX);
        }
    }

    /**
     * Инициализирует переменную $mode, в которой хранится тип
     * "упаковки"
     *
     * @void
     *
     * @access private
     */

    function get_mode()
    {
        if (ereg (www.php.net/ereg)("^(.*)(\*)$", $this->package)) {
            $this->mode = self::END_PACK;
        } else {
            if (preg_match (www.php.net/preg_match)('{ ( ^ | [^a-z] ) \(\*\) $ }xs', $this->package) != 0) {
                $this->mode = self::ALL_PACK;
            } else {
                $this->mode = self::ONE_PACK;
            }
        }
    }

    /**
     * @void
     *
     * @access private
     */

    function import_load($File)
    {
        if (is_array (www.php.net/is_array)($File)) {
            foreach($File as $k => $v) {
                $File[$k] = self::import_load($v);
            }
        } else {
            if (file_exists (www.php.net/file_exists)($File)) {
                require_once($File);
            }
        }
    }

    /**
     * @void
     *
     * @access private
     */

    function recurs_open($directory)
    {
        if ($dir = opendir (www.php.net/opendir)($directory)) {
            while (($files = readdir (www.php.net/readdir)($dir)) !== false) {
                if ($files{0} == '.') {
                    continue;
                }
                if(is_dir (www.php.net/is_dir)($directory . $files . DIRECTORY_SEPARATOR)) {
                    self::recurs_open($directory . $files . DIRECTORY_SEPARATOR);
                } else {
                    if ($files != "") {
                        $this->string .= $directory . $files . "|";
                    }
                }
            }
        } else {
            self::error(self::NOTEXISTS);
        }
        $this->package = $this->string;
    }

    /**
     * Генерирует ошибку и осуществляет завершение выполнения
     * скрипта.
     *
     * @void
     *
     * @access private
     */

    function error($errorNum)
    {
        $errors = array (www.php.net/array)(
            self::NOTEXISTS  => "file or package not exists",
            self::SYNTAX     => "bad syntax for name of package",
        );
        if (!isset (www.php.net/isset)($errors[$errorNum])) {
            exit (www.php.net/exit)();
        }
        trigger_error (www.php.net/trigger_error)('import(' . $this->package . ') : ' . $errors[$errorNum], E_USER_ERROR);
        exit (www.php.net/exit)();
    }
}

?>
Back to top
View user's profile Send private message
Programmer
Участник форума



Joined: 23 Sep 2005
Posts: 43
Карма: 2
   поощрить/наказать


PostPosted: Tue Nov 22, 2005 12:49 pm (спустя 1 час 24 минуты; написано за 9 минут 44 секунды)
   Post subject:
Reply with quote

Дмитрий Котеров, к примеру, у меня есть библиотека, состоящая из интерфейса, описывающего построение html-страниц, и, допустим, три реализаций этого интерфейса: построение форм, таблиц, форматирование текста. В свою очередь каждая из этих библиотек требует специальный класс ошибок, который расположен для удобства в package System. Класс ошибок из System, как и все остальные вышеназванные классы требуют свойства объекта Options, который считывает параметры из соответствующего .xml файла. Как выйти из подобной ситуации? Объектов много. Связаны они между собой очень тесно. Подключать для каждого файла его "сородичей" и специальные файлы, IMHO, не очень красиво, так как при изменении структуры каталогов, где храняться библиотеки, придется все пути переписывать. Также при большом количестве классов, реализующих тот же интерфейс для построения html-страниц, просматривать большой список подключений вначале файла класса довольно сложное занятие при тесном "сотрудничестве" классов разных "упаковок".
Back to top
View user's profile Send private message
standov
Guest





Карма: 388
   поощрить/наказать


PostPosted: Tue Jan 17, 2006 1:29 pm (спустя 1 месяц 25 дней 39 минут; написано за 21 секунду)
   Post subject:
Reply with quote

Господа, почитайте php.com.ua/ru/articles/bicycles/loader.htm
Back to top
Display posts from previous:   
Post new topic   Reply to topic All times are GMT + 3 Hours
Page 1 of 1    Email to a Friend.
You cannot post new topics in this forum. You cannot reply to topics in this forum. You cannot edit your posts in this forum. You cannot delete your posts in this forum. You cannot vote in polls in this forum. You cannot attach files in this forum. You can download files in this forum.
XML