2011-03-22 16 views
5

Seviye N kategori derinliği için bir rota yazmaya çalışıyorum. Yani bir olağan kategori URL şöyle olacaktır:Zend Çerçeve rotası: bilinmeyen sayıda param

http://website/my-category/my-subcategory/my-subcategory-level3/my-subcategory-level4 

O bilinmeyen bir derinliğe sahiptir ve benim rota olası tüm düzeylerde birbirini tutmalıdır. Bunun için bir yol yaptım, ama tüm paramları kontrolörden alamıyorum.

$routeCategory = new Zend_Controller_Router_Route_Regex(
    '(([a-z0-9-]+)/?){1,}', 
     array(
      'module' => 'default', 
      'controller' => 'index', 
      'action' => 'index' 
     ), 
     array(1 => 'path'), 
     '%s' 
); 
$router->addRoute('category', $routeCategory); 

Eşleşen paramları denetleyiciye göndermek için bir yol bulamıyorum. Daha iyi bir çözümün varsa, önerilere açığım! örnek olarak

resources.router.routes.catalog-display.route = /catalog/item/:id 
resources.router.routes.catalog-display.defaults.module = catalog 
resources.router.routes.catalog-display.defaults.controller = item 
resources.router.routes.catalog-display.defaults.action = display 

:

cevap

4

İhtiyaçlarıma uygun olduğunu düşündüğüm bir çözüm buldum. Buraya girdiğim aynı şeyle sonuçlanacak insanlar için buraya göndereceğim.

Sorun:

  • + için, diğer modülleri için (admin Zend Framework varsayılan yönlendirme korumak category/subcategory/../page.html
  • gibi nesne N kategorisi için category/subcategory/subsubcategory/...
  • özel yolu gibi seviye N kategorisi için özel rota gerek örnek)
  • URL toplaması URL yardımcısı

Çözüm:

:

  • oluşturmak Özel bir rota sınıfı

Gerçek bir kod (bir başlangıç ​​noktası olarak Zend_Controller_Router_Route_Regex kullanılan bu yüzden assemble() yönteminden faydalanabilir)

<?php class App_Controller_Router_Route_Category extends Zend_Controller_Router_Route_Regex { public function match($path, $partial = false) { if (!$partial) { $path = trim(urldecode($path), '/'); } $values = explode('/', $path); $res = (count($values) > 0) ? 1 : 0; if ($res === 0) { return false; } /** * Check if first param is an actual module * If it's a module, let the default routing take place */ $modules = array(); $frontController = Zend_Controller_Front::getInstance(); foreach ($frontController->getControllerDirectory() as $module => $path) { array_push($modules, $module); } if(in_array($values[0], $modules)) { return false; } if ($partial) { $this->setMatchedPath($values[0]); } $myValues = array(); $myValues['cmsCategory'] = array(); // array_filter_key()? Why isn't this in a standard PHP function set yet? :) foreach ($values as $i => $value) { if (!is_int($i)) { unset($values[$i]); } else { if(preg_match('/.html/', $value)) { $myValues['cmsObject'] = $value; } else { array_push($myValues['cmsCategory'], $value); } } } $values = $myValues; $this->_values = $values; $values = $this->_getMappedValues($values); $defaults = $this->_getMappedValues($this->_defaults, false, true); $return = $values + $defaults; return $return; } public function assemble($data = array(), $reset = false, $encode = false, $partial = false) { if ($this->_reverse === null) { require_once 'Zend/Controller/Router/Exception.php'; throw new Zend_Controller_Router_Exception('Cannot assemble. Reversed route is not specified.'); } $defaultValuesMapped = $this->_getMappedValues($this->_defaults, true, false); $matchedValuesMapped = $this->_getMappedValues($this->_values, true, false); $dataValuesMapped = $this->_getMappedValues($data, true, false); // handle resets, if so requested (By null value) to do so if (($resetKeys = array_search(null, $dataValuesMapped, true)) !== false) { foreach ((array) $resetKeys as $resetKey) { if (isset($matchedValuesMapped[$resetKey])) { unset($matchedValuesMapped[$resetKey]); unset($dataValuesMapped[$resetKey]); } } } // merge all the data together, first defaults, then values matched, then supplied $mergedData = $defaultValuesMapped; $mergedData = $this->_arrayMergeNumericKeys($mergedData, $matchedValuesMapped); $mergedData = $this->_arrayMergeNumericKeys($mergedData, $dataValuesMapped); /** * Default Zend_Controller_Router_Route_Regex foreach insufficient * I need to urlencode values if I bump into an array */ if ($encode) { foreach ($mergedData as $key => &$value) { if(is_array($value)) { foreach($value as $myKey => &$myValue) { $myValue = urlencode($myValue); } } else { $value = urlencode($value); } } } ksort($mergedData); $reverse = array(); for($i = 0; $i < count($mergedData['cmsCategory']); $i++) { array_push($reverse, "%s"); } if(!empty($mergedData['cmsObject'])) { array_push($reverse, "%s"); $mergedData['cmsCategory'][] = $mergedData['cmsObject']; } $reverse = implode("/", $reverse); $return = @vsprintf($reverse, $mergedData['cmsCategory']); if ($return === false) { require_once 'Zend/Controller/Router/Exception.php'; throw new Zend_Controller_Router_Exception('Cannot assemble. Too few arguments?'); } return $return; } } 

Kullanım:

Rota:

$routeCategory = new App_Controller_Router_Route_Category(
     '', 
     array(
      'module' => 'default', 
      'controller' => 'index', 
      'action' => 'index' 
     ), 
     array(), 
     '%s' 
); 
$router->addRoute('category', $routeCategory); 

URL Helper: getAllParams ile kontrol edilmelidir

echo "<br>Url: " . $this->_helper->url->url(array(
          'module' => 'default', 
          'controller' => 'index', 
          'action' => 'index', 
          'cmsCategory' => array(
           'first-category', 
           'subcategory', 
           'subsubcategory') 
          ), 'category'); 

Örnek çıktı()

["cmsCategory"]=> 
    array(3) { 
    [0]=> 
    string(15) "first-category" 
    [1]=> 
    string(16) "subcategory" 
    [2]=> 
    string(17) "subsubcategory" 
    } 
    ["cmsObject"]=> 
    string(15) "my-page.html" 
    ["module"]=> 
    string(7) "default" 
    ["controller"]=> 
    string(5) "index" 
    ["action"]=> 
    string(5) "index" 
  • Not cmsObject URL, bu bir örnek verebilir category/subcategory/subsubcategory/my-page.html
+1

Bu gerçekten iyi bir şey Bogdan :) – MiPnamic

+0

Teşekkürler, MiPnamic! Bunun için gerçekten biraz düşündüm :) –

2

Ben sadece ilk parametre ve sonra rotayı

Rota denetleyici içindeki tüm params almak diğerlerini yönlendirdim ... yolları olmadan yaptık: Bunu katalog için, daha sonra itemController ekranına getiriyorumAksiyon $ i-> getRequest() -> getParams() için kontrol ettim, buradaki nokta (ama bunu bildiğinizi düşünüyorum) tüm paramları oku anahtar/değer olarak iletilir, örneğin: "site.com/catalog/item/15/kind/hat/color/red/size/M" şu şekilde bir dizi oluşturur: $params['controller'=>'catalog','action'=>'display','id'=>'15','kind'=>'hat','color'=>'red','size'=>'M'];

+0

gibi bir şey lütfen içeriyorsa yalnızca ayarlanır? –

+0

İstediğim şey olduğundan emin değilim. Bu şekilde, etrafa saçılan denetleyicideki birçok değişkenle sonuçlanacağım. Her neyse, bir çözüm buldum, bu yüzden aşağıda yazdım. –

İlgili konular