【问题标题】:Using symfony2 routing component (outside of symfony2)使用 symfony2 路由组件(在 symfony2 之外)
【发布时间】:2011-10-06 19:12:20
【问题描述】:

我一直在搜索,并没有真正找到太多有用的信息。我希望将 symfony2 路由组件(以及 yaml 组件)与我自己的个人框架一起使用,但尚未找到任何有关基本设置的文档。 symfony site 上的文档很好地解释了如何使用该组件,但在独立设置方面没有太多帮助。

谁能推荐一个可以解释如何设置单个 symfony2 组件的好地方?

【问题讨论】:

  • 好问题!我目前想知道完全相同!

标签: symfony routing components yaml


【解决方案1】:

我最终查看了symfony site 上的文档以及 github 上的源代码(Route.phpRouteCollection.phpRouteCompiler.php),并提出了我自己的基本路由器。

就像 symfony 一样,我允许将 4 个参数传递给路由类 -> 1) 模式,2) 默认控制器/动作,3) 模式中每个变量的正则表达式要求,以及 4) 任何选项 -我还没有为此编写代码,因为它不在我的要求中。

我的主/前端控制器 (index.php) 只与静态路由器类对话,该类可以访问 lib\route 命名空间中的其他路由类。

Router::Map 基本上编译一个正则表达式字符串(以及默认控制器/动作和变量名称),该字符串被传递给在 Router::_Process 中用于匹配 httpRequest 的已编译RouteCollection。从那里开始,如果在 process 方法中有匹配项,那么我根据匹配的 compiledRoute 默认控制器/动作的值设置控制器/动作/参数。如果没有 preg_match,那么我使用请求对象中的默认控制器/动作/参数。剩下的就是蛋糕了……

我希望有人觉得这很有用,并且能够节省我今天花在这方面的时间。干杯!

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());

路由器.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;
}
}

路由.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;
}
}

【讨论】:

  • 你不使用 symfony2 组件。您刚刚编写了自己的前端控制器。伟大的。但这不是问题所在!?
  • @Raffael1984 我使用 symfony 2 路由组件作为路由的基础。当我没有得到答案时,我决定简化 symfony 路由器以满足我的需要。似乎这就是答案,如果您查看源代码,这将几乎解释它是如何工作的,以及在您理解它之后如何将其合并到您的框架中。
  • easy 朋友...我和您有同感...当前有关特定组件的文档还不够标准。顺便说一句,到目前为止,我发现你在他们的 IRC 频道上得到了关于 sf2 内容的非常有能力的反馈......看看那里。
猜你喜欢
  • 2015-07-26
  • 1970-01-01
  • 2011-07-18
  • 1970-01-01
  • 1970-01-01
  • 2014-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多