2013-05-22 4 views
2

Я пытаюсь создать собственную инфраструктуру для внутреннего использования. Я получил структуру, как это:PHP: автозагрузка нескольких классов с пространствами имен

index.php 
boot/
    booter.php 
application/
    controllers/
      indexcontroller.php 
core/
    template.class.php 
    model.class.php 
    controller.class.php 
    cache/
     memcached.php 
    something/
     something.php 

Booter.php содержит: (он в настоящее время работает только с файлами, расположенными в каталоге ядра):

class Booter 
{ 
private static $controller_path, $model_path, $class_path; 

public static function setDirs($controller_path = 'application/controllers', $model_path = 'application/models', $classes_path = 'core') 
{ 
    self::$controller_path = $controller_path; 
    self::$model_path  = $model_path; 
    self::$class_path  = $classes_path; 

    spl_autoload_register(array('Booter', 'LoadClass')); 
    if (DEBUG) 
     Debugger::log('Setting dirs...'); 
} 

protected static function LoadClass($className) 
{ 
    $className = strtolower($className); 

    if (file_exists(DIR . '/' . self::$model_path . '/' . $className . '.php')) 
    { 
     require(DIR . '/' . self::$model_path . '/' . $className . '.php'); 
    }  
    else if (file_exists(DIR . '/' . self::$class_path . '/' . $className . '.class.php')) 
    { 
     require(DIR . '/' . self::$class_path . '/' . $className . '.class.php'); 
    } 
    else if (file_exists(DIR . '/' . self::$controller_path . '/' . $className . '.php')) 
    { 
     require(DIR . '/' . self::$controller_path . '/' . $className . '.php'); 
    } 

    if (DEBUG) 
     Debugger::log('AutoLoading classname: '.$className); 
} 
} 

Мое приложение/контроллеры/IndexController выглядит следующим образом:

<? 
class IndexController extends Controller 
{ 
    public function ActionIndex() 
    { 
      $a = new Model; // It works 
      $a = new Controller; //It works too 
    } 
} 

?> 

И здесь приходит на мои вопросы:

[Вопрос 1]

Мой код в настоящее время работает следующим образом:

$a = new Model; // Class Model gets included from core/model.class.php 

Как я могу реализовать в том числе файлов по классам с пространствами имен? Например:

$a = new Cache\Memcached; // I would like to include file from /core/CACHE/Memcached.php 
$a = new AnotherNS\smth; // i would like to include file from /core/AnotherNS/smth.php 

и так далее. Как я могу обработать пространство имен?

[Вопрос 2]

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

ответ

2

Вопрос 1:

В вашем заряжания, измените \ (для пространства имен) в DIRECTORY_SEPARATOR. Это должно работать:

protected static function LoadClass($className) 
{ 
    $className = strtolower($className); 
    $className = str_replace('\\', DIRECTORY_SEPARATOR, $className); 
... 
} 

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

Вопрос 2:

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

2

У меня обычно есть файл bootstrap.php внутри папки conf, которая находится в корне приложения. Мой код обычно находится внутри папки src, который также находится в корневом каталоге, так это отлично работает для меня:

<?php 

define('APP_ROOT', dirname(__DIR__) . DIRECTORY_SEPARATOR); 

set_include_path(
    implode(PATH_SEPARATOR, 
     array_unique(
      array_merge(
       array(
        APP_ROOT . 'src', 
        APP_ROOT . 'test' 
       ), 
       explode(PATH_SEPARATOR, get_include_path()) 
      ) 
     ) 
    ) 
); 

spl_autoload_register(function ($class) { 
    $file = sprintf("%s.php", str_replace('\\', DIRECTORY_SEPARATOR, $class)); 
    if (($classPath = stream_resolve_include_path($file)) != false) { 
     require $classPath; 
    } 
}, true); 

Вы можете обобщить это в свой класс «Загрузчик» и добавить каталоги к включают пути. Если у вас есть хорошо определенные имена пространства имен, проблем с коллизиями не будет.

Редактировать: Это работает, если вы следуете PSR-1.

Смежные вопросы