2016-06-16 34 views
0

我们从样本非标准路线Zend的2路由器 - 可选参数未知

  array(
       'type' => 'Literal', 
       'options' => array(
        'route' => '/application', 
        'defaults' => array(
         '__NAMESPACE__' => 'Application\Controller', 
         'controller' => 'Index', 
         'action'  => 'index', 
        ), 
       ), 
       'may_terminate' => true, 
       'child_routes' => array(
        'default' => array(
         'type' => 'Segment', 
         'options' => array(
          'route' => '/[:controller[/:action]]', 
          'constraints' => array(
           'controller' => '[a-zA-Z][a-zA-Z0-9_-]*', 
           'action'  => '[a-zA-Z][a-zA-Z0-9_-]*', 
          ), 
          'defaults' => array(
          ), 
         ), 
        ), 
       ), 
       'priority' => -1000, 
      ), 

它可以理解如

/application 
/application/some 
/application/index/about 

网址,但它不明白的URL像

/application/index/about/param1/val1/param2/val2/... 

在Zend1被*,我们可以将其添加到像这样的路线

'route' => '/:controller/:action/*', 

*之后的所有参数都试图用斜杠分割。问题:zend 2有没有办法创建具有未知参数名称的路由?一种解决方案是创建自己的路由类型,但可能存在内置解决方案?

UPD

我已经写我自己Route类,它分析*上ROURE端,以及非必需的参数将在ZF1风格解析。

<?php 

namespace Engine\Mvc\Router\Http; 

use Zend\I18n\Translator\TranslatorInterface as Translator; 
use Zend\Mvc\Router\Exception; 
use Zend\Stdlib\RequestInterface as Request; 

class Segment extends \Zend\Mvc\Router\Http\Segment 
{ 
    protected $unknownParameterParse = false; 
    protected $route = null; 
    public function __construct($route, array $constraints = [], array $defaults = []) 
    { 
     if ($route{mb_strlen($route)-1} == '*'){ 
      $route = mb_substr($route, 0, mb_strlen($route)-1); 
      $this->unknownParameterParse = true; 
     } 
     $this->route = $route; 
     parent::__construct($route, $constraints, $defaults); 
    } 

    public function assemble(array $params = [], array $options = []) { 
     $path = parent::assemble($params, $options); 
     if ($this->unknownParameterParse){ 
      $unknowns = []; 

      foreach($params as $key=>$value){ 
       if (strpos($this->route, ':'.$key)===false){ 
        $unknowns[] = $this->encode($key) . '/'. $this->encode($value); 
       } 
      } 
      if ($unknowns){ 
       $path = rtrim($path, '/').'/'.implode('/', $unknowns); 
      } 
     } 
     return $path; 
    } 

    public function match(Request $request, $pathOffset = null, array $options = []) 
    { 
     if (!method_exists($request, 'getUri')) { 
      return; 
     } 

     $uri = $request->getUri(); 
     $path = $uri->getPath(); 

     $regex = $this->regex; 

     if ($this->translationKeys) { 
      if (!isset($options['translator']) || !$options['translator'] instanceof Translator) { 
       throw new Exception\RuntimeException('No translator provided'); 
      } 

      $translator = $options['translator']; 
      $textDomain = (isset($options['text_domain']) ? $options['text_domain'] : 'default'); 
      $locale  = (isset($options['locale']) ? $options['locale'] : null); 

      foreach ($this->translationKeys as $key) { 
       $regex = str_replace('#' . $key . '#', $translator->translate($key, $textDomain, $locale), $regex); 
      } 
     } 

     if ($pathOffset !== null) { 
      $result = preg_match('(\G' . $regex . ')', $path, $matches, null, $pathOffset); 
     } else { 
      $result = preg_match('(^' . $regex . ($this->unknownParameterParse ? '' : '$') . ')', $path, $matches); 
     } 


     if (!$result) { 
      return; 
     } 
     $matchedLength = strlen($matches[0]); 
     $params  = []; 

     foreach ($this->paramMap as $index => $name) { 
      if (isset($matches[$index]) && $matches[$index] !== '') { 
       $params[$this->decode($name)] = $this->decode($matches[$index]); 
      } 
     } 

     /*ENGINE get not defined params*/ 
     if ($this->unknownParameterParse){ 
      $otherParams = explode("/", trim(substr($path, strlen($matches[0])), "/")); 
      foreach($otherParams as $i=>$param){ 
       if ($i%2 == 0){ 
        $pairKey = $param; 
       }else{ 
        $params[$pairKey] = $param; 
       } 
      } 
     } 
     /* endof get not defined params */ 
     return new \Zend\Mvc\Router\Http\RouteMatch(array_merge($this->defaults, $params), $matchedLength); 
    } 
} 

怎么说chaoss88它完美地做通配符路线:我们可以用分段式,并与通配符类型的子路径父路径。但上面的一些更亲近的人。这样的路线:

'route' => '/core/:controller[/:action]*' 

工作良好。但是,如果您使用ZF2路由器作为请求过滤的授权,通配符路由器存在安全问题 - 这就是为什么它已被弃用。但我认为路由器是用于URL解析/组装,而不是过滤:对于过滤/验证ZF2有更好的解决方案。

+0

我其实不知道它是否可以工作,但你可以尝试[正则表达式路由](http://framework.zend.com/manual/current/en/modules/zend.mvc.routing.html#zend -mvc-router-http-regex) – jbrtrnd

+0

Regexp没有动态参数化。但是我已经解决了路由器的问题,扩展了\ Zend \ Mvc \ Router \ Http \ Segment。 –

回答

0

我觉得通配符是你正在寻找:

  'child_routes' => array(
       'default' => array(
        'type' => 'Wildcard', 
        'options' => array(
          'key_value_delimiter' => '/', 
          'param_delimiter' => '/' 
          ) 
        ), 
      ), 
+1

由于安全问题,很久以前不推荐使用通配符路由类型。 http://framework.zend.com/manual/current/en/modules/zend.mvc.routing.html#zend-mvc-router-http-wildcard-deprecated – edigu

+0

好的解决方案,谢谢!关于安全性 - 我认为,潜在的不安全请求参数必须在控制器中验证手动操作。这是旧的网络开发规则 - 任何数据都可以输入。 –

0

我不知道这些参数应该代表但您的例子,它看起来像你可以/应该使用的查询参数,这些参数而不是路由参数。

application/index/about?param1=val1&param2=val2&... 

有了这样的网址,你可以做以下的控制器,让您的查询参数:

$param1 = $this->params()->fromQuery('param1'); // val1 
$param1 = $this->params()->fromQuery('param2'); // val2 

,你可以得到控制和行动这样可以按如下步骤发送请求:

$controller = $this->params()->fromRoute('controller'); // index 
$action = $this->params()->fromRoute('action'); // about 

您不必在您的路由配置中更改任何内容以使其工作。
也请检查this answer here