Как лучше всего расширить мой загрузчик модулей?

#php #file

#php #файл

Вопрос:

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

Я придумал это изначально.

 // Try to load a module
$file_path = $segments[1] . '/' . $segments[2] . '/' . ucwords($segments[2]) . '.php';
$paths = array (
    'third-party' => SYS . 'extensions/third-party/modules/',
    'core' => SYS . 'extensions/core/modules/'
);

foreach ( $paths as $path) {
    if ( file_exists($path . $file_path)) {
        require($path . $file_path);
        if ( class_exists($segments[2])) {
            $module = new $segments[2];
            $function = isset($segments[3]) ? $segments[3] : 'index';
            if (method_exists($module, $function)) {
                $variables = $this->Router->get_variables(3);

                // Define Module Path
                define("MODULE_PATH", $path . $segments[1] . '/' . $segments[2] . '/');

                return call_user_func_array(array($module, $function), $variables);
            }
        }
    }
}
  

Это работает следующим образом.

Если вы введете admin / user в URL. В более ранней части моего скрипта он ищет класс admin. Если он находит класс admin, он ищет пользовательскую функцию. Если пользовательская функция не может быть найдена. Приведенный выше код вызывается для поиска модуля.

Этот модуль будет найден в.

xxx/modules/admin/user/User.php

Приведенный выше код проверяет, существует ли этот файл, проверяет, существует ли класс, определяет, какую функцию следует вызвать, проверяет, существует ли функция внутри класса, затем вызывает функцию.

Что я хочу сделать, так это проверить наличие любого уровня этого.

Например.

?администратор/ пользователь/ регистрация

Это можно найти по адресу.

xxx/modules/admin/user/register/Register.php

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

Ответ №1:

Лучше всего было бы (при инициализации) просмотреть все файлы в ваших целевых каталогах (то есть те, где могут быть модули) и создать массив индексов, который будет выглядеть примерно так (для myFile.php предполагая, что он находится в «modules/something/myDir/mySubdir/):

 [0] = "mySubdir"
[1] = "myDir"
[2] = "something"
[3] = "modules"
  

Теперь, когда у вас есть путь, подобный приведенному вами примеру (?admin /user / register), используйте эту функцию, она должна найти соответствие в файлах, предполагая, что они хранятся в массиве and, со значениями ключей, равными их имени файла:

 function hasMatch($file_path, $file_index){
    // file_path  = the requested file path, WITHOUT leading ? or any kind of
    //              character, not containing the actual filename, just path

    // file_index = index of the files, an array keyed with filenames, containing
    //              its super-directories

    // returns the full include path on success, otherwise FALSE

    $file_path_array = array_reverse(explode("/", $file_path));

    foreach ($file_index as $file_name => $file_in){
        $found_start = false;
        $found_end = -1;

        $pi = 0;
        for ($fi = 0; $fi < count($file_in); $fi  ){
            if ($file_in[$fi] == $file_path_array[$pi]){
                if ($found_start == false){
                    $found_start = true;
                }
                $found_end = $pi;
                $pi  ;
            } else if ($found_start != false){
                if ($found_end == count($file_path_array)){
                    // match
                    $ret = "";

                    foreach ($file_in as $file_dir){
                        $ret = $file_dir."/".$ret;
                    }

                    return $ret.$file_name;
                }
            }
        }
    }

    return false; // no match
}
  

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

Кроме того, я не тестировал приведенный выше код, поэтому может быть небольшой недостаток, или, возможно, я не использовал функцию API там, где мог. Ну что ж. Я думаю, вы поймете идею.