Просмотр поста

.
Screamer

Ну и я свой вариант подкину.

// Подключаем и проверяем конфиг.

$config = require 'assets/conf/router.php';
$required = array('default' => 'string', 'error' => 'string');
$error = array();

foreach ($config as $key => $value) {
if (!array_key_exists($key, $required)) {
$error[] = '"' . $key . '"" element should be defined in the basic configuration.';
} else {
$type = 'is_' . $required[$key];
if (!$type($value)) {
$error[] = 'Invald type of "' . $key . '". Element should be a ' . $required[$key] . '.';
} else {
unset($required[$key]);
}
}
}

if (!empty($required)) {
$error[] = 'Missing: ' . implode(', ', array_keys($required));
}

if (!empty($error)) {
throw new Exception('The following errors occured:' . "\r\n" . implode("\r\n", $error) . "\r\n" . 'Check your router configuration file.');
}

// Рзбираем URI

// Parse URI
$uri = isset($_SERVER['REQUEST_URI']) && is_string($_SERVER['REQUEST_URI'])
? explode('/', trim($_SERVER['REQUEST_URI'], '\/ ')) 
: array();
$module = isset($uri[0]) && trim($uri[0]) != '' ? trim($uri[0]) : $config['default'];
$controller = isset($uri[1]) && trim($uri[1]) != '' ? trim($uri[1]) : 'index';
$action = isset($uri[2]) && trim($uri[2]) != '' ? trim($uri[2]) : 'view';
$args = sizeof($uri) > 3 ? array_slice($uri, 3) : array();

// Пробуем создать объект контроллера.
// Здесь подразумевапеся, что файл будет подключён автоматически с помощью функции заданной через spl_autoload_register
// Класс контроллера должен находиться в пространстве имён \modules\имя_модуля\controller
// Путь к файлу контроллёра должен быть следующим: ~/modules/имя_модуля/controller/имя_класса_контроллера.расширение_заданное_в_автозагрузчике

$class = '\modules\\' . $module . '\controller\\' . ucwords($controller);

try {
$object = new $class(/* TODO: pass args */); // Сюда нужно передать аргументы, которые требует родительский контроллёр
} catch (\Exception $e) {
// Проверяем, не является ли запрашиваемый контроллёр страницей ошибки, воизбежание зацикливания редиректа.
if ($module == $config['error'] && $controller == 'index') {
throw new Exception('Error page is not exists.');
} else {
redirect($config['error']); // Перенаправляем на страницу ошибки.
}
}

// Проверяем, наследуется ли контроллёр от нужного нам класса.
if (!$object instanceof \Controller) {
throw new Exception('Object of controller should be instance of \Controller');
}

// Проверка метода на существование.
// Здесь тоже следовало бы проверять, не отвечает ли контроллёр за страницу ошибки.
// Но так как родительский контроллер имеет абстрактный метод, который отвечает за страницу по умолчанию, в этом нужды нет.
// PHP предупредит нас об этом заранее.
$action = 'action_' . $action;
if (!method_exists($controller, $action)) {
redirect($config['error']);
}

// Вызываем метод контроллёра попутно передав ему аргументы, которые были получены из URI
$result = strval(call_user_func_array(array($controller, $action), $args));

if (headers_sent()) {
// Если заголовки были отправлены, то обрабатываем их. Например можно записать выведенные данные в лог. Вероятно где-то произошла ошибка.
// ...
} else {
// Если метод возвратил не пустую строку, то загружаем шаблонизатор и выводим полученные данные.
if (!empty($result) && is_string($result)) {
$tpl = new \Template();
header('Content-type: application/xhtml+xml; charset=utf-8');
echo $tpl->load('index', 'contents' => $result);
} else {
// Если метод вернул другой тип данных, то обрабатываем его так, как нам нужно.
// Например метод вернул массив, значит его можно отобразить в виде json строки, что мы и сделаем.
if (is_array($result)) {
echo json_encode($result);
}
}
}