Использование компонента маршрутизации symfony2 (вне symfony2) - PullRequest
4 голосов
/ 16 июля 2011

Я искал и не нашел много полезной информации. Я собираюсь использовать компонент маршрутизации symfony2 (а также компонент yaml) с моей личной структурой, но не нашел никакой документации по базовой настройке. Документация на сайте symfony хорошо объясняет, как использовать компонент, но не так много, как автономная установка.

Кто-нибудь может порекомендовать хорошее место для начала, которое может объяснить, как настроить отдельные компоненты symfony2?

1 Ответ

0 голосов
/ 18 июля 2011

В итоге я посмотрел документацию на сайте symfony , а также исходный код на github ( Route.php , RouteCollection.php , RouteCompiler.php ) и придумал свой базовый роутер.

Точно так же, как symfony, я разрешаю передать 4 аргумента классу маршрута -> 1) шаблон, 2) контроллер / действие по умолчанию, 3) требования регулярного выражения для каждой переменной в шаблоне и 4) любые параметры - Я еще не кодировал это, поскольку это не соответствует моим требованиям.

Мой главный / фронт-контроллер (index.php) общается только со статическим классом Router, у которого есть доступ к другим классам маршрутизации в пространстве имен lib \ route.

Router :: Map в основном компилирует строку регулярного выражения (вместе с именами контроллера / действия по умолчанию и переменных), которые передаются в compiledRouteCollection, которая используется в Router :: _ Process для сопоставления с httpRequest. Оттуда, если есть совпадение в методе процесса, тогда я устанавливаю контроллер / действие / аргументы на основе значений соответствующего контроллера / действия по умолчанию compiledRoute. Если нет preg_match, тогда я использую контроллер по умолчанию / action / args из объекта запроса. Остальное - торт ...

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

index.php

require_once 'config/config.php';
require_once 'lib/autoload.php';
lib\Router::Map(
    'users_username_id',
    'users/{username}/{id}',
    array('controller' => 'testController', 'action' => 'users')
);
lib\Router::Route(new lib\Request());

router.php

namespace lib;

class Router {
protected static $_controller;
protected static $_action;
protected static $_args;
protected static $_compiledRouteCollection;
private static $_instance;

private function __construct() {
    self::$_compiledRouteCollection = new \lib\route\CompiledRouteCollection();
}

public static function Singleton() {
    if(!isset(self::$_instance)) {
        $className = __CLASS__;
        self::$_instance = new $className;
    }
    return self::$_instance;
}

public static function Route(Request $request, $resetProperties = false) {
    self::Singleton();

    self::_Process($request,$resetProperties);

    $className = '\\app\\controllers\\' . self::$_controller;
    if(class_exists($className, true)) {
        self::$_controller = new $className;

        if(is_callable(array(self::$_controller, self::$_action))) {
            if(!empty(self::$_args)) {
                call_user_func_array(array(self::$_controller, self::$_action), self::$_args);
            } else {
                call_user_func(array(self::$_controller, self::$_action));
            }
            return;
        }
    }
    self::Route(new \lib\Request('error'),true);
}

public static function Map($name, $pattern, array $defaults, array $requirements = array(), array $options = array()) {
    self::Singleton();
    $route = new \lib\route\Route($pattern,$defaults,$requirements,$options);
    $compiledRoute = $route->Compile();
    self::$_compiledRouteCollection->Add($name,$compiledRoute);
}

private static function _Process(Request $request, $resetProperties = false) {
    $routes = array();
    $routes = self::$_compiledRouteCollection->routes;
    foreach($routes as $route) {
        preg_match($route[0]['regex'], $request->GetRequest(), $matches);
        if(count($matches)) {
            array_shift($matches);
            $args = array();
            foreach($route[0]['variables'] as $variable) {
                $args[$variable] = array_shift($matches);
            }
            self::$_controller = (!isset(self::$_controller) || $resetProperties) ? $route[0]['defaults']['controller'] : self::$_controller;
            self::$_action = (!isset(self::$_action) || $resetProperties) ? $route[0]['defaults']['action'] : self::$_action;
            self::$_args = (!isset(self::$_args) || $resetProperties) ? $args : self::$_args;

            return;
        }
    }
    self::$_controller = (!isset(self::$_controller) || $resetProperties) ? $request->GetController() : self::$_controller;
    self::$_action = (!isset(self::$_action) || $resetProperties) ? $request->GetAction() : self::$_action;
    self::$_args = (!isset(self::$_args) || $resetProperties) ? $request->GetArgs() : self::$_args;
}
}

request.php

namespace lib;

class Request {
protected $_controller;
protected $_action;
protected $_args;
protected $_request;

public function __construct($urlPath = null) {
    $this->_request = $urlPath !== null ? $urlPath : $_SERVER['REQUEST_URI'];

    $parts = explode('/', $urlPath !== null ? $urlPath : $_SERVER['REQUEST_URI']);
    $parts = array_filter($parts);

    $this->_controller = (($c = array_shift($parts)) ? $c : 'index').'Controller';
    $this->_action = ($c = array_shift($parts)) ? $c : 'index';
    $this->_args = (isset($parts[0])) ? $parts : array();
}

public function GetRequest() {
    return $this->_request;
}

public function GetController() {
    return $this->_controller;
}

public function GetAction() {
    return $this->_action;
}

public function GetArgs() {
    return $this->_args;
}
}

route.php

namespace lib\route;

class Route {
private $_pattern;
private $_defaults;
private $_requirements;
public $_options;

public function __construct($pattern, array $defaults = array(), array $requirements = array(), array $options = array()) {
    $this->SetPattern($pattern);
    $this->SetDefaults($defaults);
    $this->SetRequirements($requirements);
    $this->SetOptions($options);
}

public function SetPattern($pattern) {
    $this->_pattern = trim($pattern);

    if($this->_pattern[0] !== '/' || empty($this->_pattern)) {
        $this->_pattern = '/'.$this->_pattern;
    }
}

public function GetPattern() {
    return $this->_pattern;
}

public function SetDefaults(array $defaults) {
    $this->_defaults = $defaults;
}

public function GetDefaults() {
    return $this->_defaults;
}

public function SetRequirements(array $requirements) {
    $this->_requirements = array();
    foreach($requirements as $key => $value) {
        $this->_requirements[$key] = $this->_SanitizeRequirement($key,$value);
    }
}

public function GetRequirements() {
    return $this->_requirements;
}

public function SetOptions(array $options) {
    $this->_options = array_merge(
        array('compiler_class' => 'lib\\route\\RouteCompiler'),
        $options
    );
}

public function GetOptions() {
    return $this->_options;
}

public function GetOption($name) {
    return isset($this->_options[$name]) ? $this->_options[$name] : null;
}

private function _SanitizeRequirement($key, $regex) {
    if($regex[0] == '^') {
        $regex = substr($regex, 1);
    }

    if(substr($regex, -1) == '$') {
        $regex = substr($regex,0,-1);
    }

    return $regex;
}

public function Compile() {
    $className = $this->GetOption('compiler_class');
    $routeCompiler = new $className;

    $compiledRoute = array();
    $compiledRoute = $routeCompiler->Compile($this);
    return $compiledRoute;
}
}

routeCompiler.php

namespace lib\route;

class RouteCompiler {

//'#\/tellme\/users\/[\w\d_]+\/[\w\d_]+#'
public function Compile(Route $route) {
    $pattern = $route->GetPattern();
    $requirements = $route->GetRequirements();
    $options = $route->GetOptions();
    $defaults = $route->GetDefaults();
    $len = strlen($pattern);
    $tokens = array();
    $variables = array();
    $pos = 0;
    $regex = '#';

    preg_match_all('#.\{([\w\d_]+)\}#', $pattern, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
    if(count($matches)) {
        foreach($matches as $match) {
            if($text = substr($pattern, $pos, $match[0][1] - $pos)) {
                $regex .= str_replace('/', '\/', $text).'\/';
            }
            if($var = $match[1][0]) {
                if(isset($requirements[$var])) {
                    $regex .= '('.$requirements[$var].')\/';
                } else {
                    $regex .= '([\w\d_]+)\/';
                }
                $variables[] = $match[1][0];
            }
            $pos = $match[0][1] + strlen($match[0][0]);

        }
        $regex = rtrim($regex,'\/').'#';
    } else {
        $regex .= str_replace('/', '\/', $pattern).'#';
    }

    $tokens[] = array(
        'regex' => $regex,
        'variables' => $variables,
        'defaults' => $defaults
    );
    return $tokens;
}
}

compiledRouteCollection.php

namespace lib\route;

class CompiledRouteCollection {
public $routes;

public function __construct() {
    $this->routes = array();
}

public function Add($name, array $route) {
    $this->routes[$name] = $route;
}
}
...