2008-10-02 45 views
12

在Kohana中/笨,我可以有一個URL形式如下:使用URL段在Zend框架的行動方法的參數

http://www.name.tld/controller_name/method_name/parameter_1/parameter_2/parameter_3 ... 

,然後閱讀在我的控制器參數如下:

class MyController 
{ 
    public function method_name($param_A, $param_B, $param_C ...) 
    { 
     // ... code 
    } 
} 

你如何在Zend框架中實現這一點?

回答

6

更新(2016年4月13日): 在下面移動,並已固定我的答案的鏈接。但是,以防萬一再次消失了 - 這裏有提供一些深入的信息,這種技術的幾個備選方案,以及使用原來的文章作爲參考材料:


@Andrew Taylor的回覆是正確的Zend Framework處理URL參數的方式。但是,如果您想在控制器的操作中使用URL參數(如您的示例中所示) - 請查看this tutorial on Zend DevZone

11

在Zend_Controller_Router類請看:

http://framework.zend.com/manual/en/zend.controller.router.html

這將允許你定義一個Zend_Controller_Router_Route中映射到您的網址,你需要的方式。

具有用於索引控制器的索引行爲4個靜則params的一個例子是:

$router = new Zend_Controller_Router_Rewrite(); 

$router->addRoute(
    'index', 
    new Zend_Controller_Router_Route('index/index/:param1/:param2/:param3/:param4', array('controller' => 'index', 'action' => 'index')) 
); 

$frontController->setRouter($router); 

這是添加到您的引導已經定義了你的前端控制器之後。

一旦你的行動,你就可以使用:

$this->_request->getParam('param1'); 

內,您的操作方法來訪問值。

安德魯

+0

尼斯,該文檔是不是在考慮那麼清楚。 – 2010-04-13 07:04:58

1

原本張貼在這裏http://cslai.coolsilon.com/2009/03/28/extending-zend-framework/

我目前的解決方案如下:

abstract class Coolsilon_Controller_Base 
    extends Zend_Controller_Action { 

    public function dispatch($actionName) { 
     $parameters = array(); 

     foreach($this->_parametersMeta($actionName) as $paramMeta) { 
      $parameters = array_merge( 
       $parameters, 
       $this->_parameter($paramMeta, $this->_getAllParams()) 
      ); 
     } 

     call_user_func_array(array(&$this, $actionName), $parameters); 
    } 

    private function _actionReference($className, $actionName) { 
     return new ReflectionMethod( 
      $className, $actionName 
     ); 
    } 

    private function _classReference() { 
     return new ReflectionObject($this); 
    } 

    private function _constructParameter($paramMeta, $parameters) { 
     return array_key_exists($paramMeta->getName(), $parameters) ? 
      array($paramMeta->getName() => $parameters[$paramMeta->getName()]) : 
      array($paramMeta->getName() => $paramMeta->getDefaultValue()); 
    } 

    private function _parameter($paramMeta, $parameters) { 
     return $this->_parameterIsValid($paramMeta, $parameters) ? 
      $this->_constructParameter($paramMeta, $parameters) : 
      $this->_throwParameterNotFoundException($paramMeta, $parameters); 
    } 

    private function _parameterIsValid($paramMeta, $parameters) { 
     return $paramMeta->isOptional() === FALSE 
      && empty($parameters[$paramMeta->getName()]) === FALSE; 
    } 

    private function _parametersMeta($actionName) { 
     return $this->_actionReference( 
       $this->_classReference()->getName(), 
       $actionName 
      ) 
      ->getParameters(); 
    } 

    private function _throwParameterNotFoundException($paramMeta, $parameters) { 
     throw new Exception(」Parameter: {$paramMeta->getName()} Cannot be empty」); 
    } 
} 
3

對於允許更復雜的配置更簡單的方法,嘗試this post。總結:

創建application/configs/routes.ini

routes.popular.route = popular/:type/:page/:sortOrder 
routes.popular.defaults.controller = popular 
routes.popular.defaults.action = index 
routes.popular.defaults.type = images 
routes.popular.defaults.sortOrder = alltime 
routes.popular.defaults.page = 1 
routes.popular.reqs.type = \w+ 
routes.popular.reqs.page = \d+ 
routes.popular.reqs.sortOrder = \w+ 

添加到bootstrap.php

// create $frontController if not already initialised 
$frontController = Zend_Controller_Front::getInstance(); 

$config = new Zend_Config_Ini(APPLICATION_PATH . ‘/config/routes.ini’); 
$router = $frontController->getRouter(); 
$router->addConfig($config,‘routes’); 
+0

但我必須爲每個控制器配置:D – Jeffrey04 2010-01-05 09:12:01

+0

這經常是有用的,我傾向於找到控制器和路由組在一起,即/ page/get/1和/ user/andy/confirm/email-confirmation-token等,雖然對於更大的應用程序,它可能會變得笨拙 – Andy 2010-01-05 11:23:43

4

我有我的控制器類擴展Zend_Controller_Action並進行了如下修改:

dispatch($action)方法代替

$this->$action();

call_user_func_array(array($this,$action), $this->getUrlParametersByPosition());

而在我的行動增加了以下方法

/** 
* Returns array of url parts after controller and action 
*/ 
protected function getUrlParametersByPosition() 
{ 
    $request = $this->getRequest(); 
    $path = $request->getPathInfo(); 
    $path = explode('/', trim($path, '/')); 
    if(@$path[0]== $request->getControllerName()) 
    { 
     unset($path[0]); 
    } 
    if(@$path[1] == $request->getActionName()) 
    { 
     unset($path[1]); 
    } 
    return $path; 
} 

現在的URL像/mycontroller/myaction/123/321

我會得到以下所有控制器的PARAMS和行動

public function editAction($param1 = null, $param2 = null) 
{ 
    // $param1 = 123 
    // $param2 = 321 
} 

URL中的其他參數不會導致任何錯誤,因爲您可以將更多參數發送給隨後定義的方法。您可以通過func_get_args() 獲得所有這些信息,而且您仍可以通常的方式使用getParam()。 您的網址可能不包含使用默認網址的操作名稱。

其實我的網址不包含參數名稱。只有他們的價值。 (正如它在問題中一樣) 而且您必須定義路徑以指定URL中的參數位置,以遵循框架的概念並能夠使用Zend方法構建URL。 但是如果你總是知道你的參數在URL中的位置,你可以很容易地得到它。

這並不像使用反射方法那麼複雜,但我想提供更少的開銷。

調度方法現在看起來是這樣的:

/** 
* Dispatch the requested action 
* 
* @param string $action Method name of action 
* @return void 
*/ 
public function dispatch($action) 
{ 
    // Notify helpers of action preDispatch state 
    $this->_helper->notifyPreDispatch(); 

    $this->preDispatch(); 
    if ($this->getRequest()->isDispatched()) { 
     if (null === $this->_classMethods) { 
      $this->_classMethods = get_class_methods($this); 
     } 

     // preDispatch() didn't change the action, so we can continue 
     if ($this->getInvokeArg('useCaseSensitiveActions') || in_array($action, $this->_classMethods)) { 
      if ($this->getInvokeArg('useCaseSensitiveActions')) { 
       trigger_error('Using case sensitive actions without word separators is deprecated; please do not rely on this "feature"'); 
      } 
      //$this->$action(); 
      call_user_func_array(array($this,$action), $this->getUrlParametersByPosition()); 
     } else { 
      $this->__call($action, array()); 
     } 
     $this->postDispatch(); 
    } 

    // whats actually important here is that this action controller is 
    // shutting down, regardless of dispatching; notify the helpers of this 
    // state 
    $this->_helper->notifyPostDispatch(); 
}