標籤:
Magento的路由系統,需要考慮到兩個抽象層。
1,首先你需要瞭解,可能會有無數多個路由對象負責處理路由邏輯,最後只有一個路由對象能夠擷取並處理該請求。預設情況下,Magento擁有四個路由對象。
2,在這四種路由對象內,又有一系列不同的規則用於匹配url地址到相應的控制器方法。這些規則非常相似,只有一些細微的差別。
路由匹配迭代過程
Magneto的路由開始於前端控制器對象的Mage_Core_Controller_Varien_Front::dispatch()方法,在如下迴圈中,選擇合適的路由對象,
01020304050607 |
while (! $request ->isDispatched() && $i ++<100) { foreach ( $this ->_routers as $router ) { if ( $router ->match( $this ->getRequest())) { break ; } } } |
Mage_Core_Controller_Varien_Front::$_routers是前端控制器類的一個屬性,用於存放系統中可用的路由規則。該屬性被定義為一個數組,預設為空白,數組鍵為路由對象表示,如admin,standard,cms,default,對應的數組值分別為執行個體化的路由對象。那麼它是如何被系統賦值的呢?在系統APP模型中執行個體化前端控制器類的時候,調用了該類的init()方法,該方法按照一定的方式,執行個體化系統中可用的路由對象,並通過addRouter()方法,將擷取到的路由對象賦值給$_routers數組,另外,在addRouter()中,每個路由對象都通過setFront()方法,獲得了前端控制器的引用。
010203040506 |
public function addRouter( $name , Mage_Core_Controller_Varien_Router_Abstract $router ) { $router ->setFront( $this ); $this ->_routers[ $name ] = $router ; return $this ; } |
回過頭來在看init()方法,下面是該方法的完整代碼,
010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445 |
public function init() { Mage::dispatchEvent( ‘controller_front_init_before‘ , array ( ‘front‘ => $this )); $routersInfo = Mage::app()->getStore()->getConfig(self::XML_STORE_ROUTERS_PATH); /* $routersInfo需要的config.xml檔案節點如下 <web> <!-- ... --> <routers> <admin> <area>admin</area> <class>Mage_Core_Controller_Varien_Router_Admin</class> </admin> <standard> <area>frontend</area> <class>Mage_Core_Controller_Varien_Router_Standard</class> </standard> </routers> <!-- ... --> </web> */ Varien_Profiler::start( ‘mage::app::init_front_controller::collect_routers‘ ); foreach ( $routersInfo as $routerCode => $routerInfo ) { if (isset( $routerInfo [ ‘disabled‘ ]) && $routerInfo [ ‘disabled‘ ]) { continue ; } if (isset( $routerInfo [ ‘class‘ ])) { $router = new $routerInfo [ ‘class‘ ]; if (isset( $routerInfo [ ‘area‘ ])) { $router ->collectRouters( $routerInfo [ ‘area‘ ], $routerCode ); } $this ->addRouter( $routerCode , $router ); } } Varien_Profiler::stop( ‘mage::app::init_front_controller::collect_routers‘ ); //這裡實際上分發事件,為了添加CMS路由對象 Mage::dispatchEvent( ‘controller_front_init_routers‘ , array ( ‘front‘ => $this )); // 最後添加預設路由 $default = new Mage_Core_Controller_Varien_Router_Default(); $this ->addRouter( ‘default‘ , $default ); return $this ; } |
如上所述,該方法只用於收集可用路由,並使用addRouter()方法添加路由對象到屬性Mage_Core_Controller_Varien_Front::$_routers中。稍微深入點的話,可以看到,在foreach迴圈中,每次執行個體化路由時,都會調用路由對象的collectRouters()方法。該方法可以在standard路由對象中一探究竟。
Magento路由分發過程解析(一):在前端控制器中擷取路由對象(轉)