2016-06-16 31 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