- Magento PHP Developer's Guide(Second Edition)
- Allan MacGregor
- 995字
- 2021-07-16 13:16:02
Routing and request flow
Before going into more detail about the different components that form a part of Magento, it is important that we understand how these components interact together and how Magento processes requests coming from the web server.
As with any other PHP application, we have a single file as an entry point for every request. In the case of Magento, this file is index.php
, which is in charge of loading the Mage.php
Bootstrap class and starting the request cycle.
- The web server receives the request and Magento is instantiated by calling the Bootstrap file
Mage.php
. - The frontend controller is instantiated and initialized. During this controller initialization, Magento searches for the web routes and instantiates them.
- Magento then iterates through each of the routers and calls the match. The match method is responsible for processing the URL and generating the corresponding controller and action.
- Instantiates the matching controller and corresponding action.
Routers are especially important in this process. Router objects are used by the frontend controller to match a requested URL (route) to a module controller and action. By default, Magento comes with the following routers:
Mage_Core_Controller_Varien_Router_Admin
Mage_Core_Controller_Varien_Router_Standard
Mage_Core_Controller_Varien_Router_Cms
Mage_Core_Controller_Varien_Router_Default
The action controller will then load and render the layout, which in turn will load the corresponding blocks, models, and templates.
Let's analyze how Magento will handle a request to a category page. We will use http://localhost/catalog/category/view/id/10
as an example. The Magento URI comprises three parts, namely FrontName/ControllerName/ActionName
.
Hence, for our example URL, the breakdown is as follows:
FrontName
: This is a catalogControllerName
: This is a categoryActionName
: This is a view
Let's take a look at the Magento router class Mage_Core_Controller_Varien_Router_Standard
match function:
public function match(Zend_Controller_Request_Http $request) { … $path = trim($request->getPathInfo(), '/'); if ($path) { $p = explode('/', $path); } else { $p = explode('/', $this->_getDefaultPath()); } … }
From the previous code, we can see that the first thing the router tries to do is parse the URI into an array. Based on our example URL, the corresponding array will be similar to the following code:
$p = Array ( [0] => catalog [1] => category [2] => view )
The next part of the function will first try to check if the request has the module name specified. If not, then it tries to determine the module name, based on the first element of our array. If a module name can't be provided, then the function will return false. Let's take a look at this part of the code:
// get module name if ($request->getModuleName()) { $module = $request->getModuleName(); } else { if (!empty($p[0])) { $module = $p[0]; } else { $module = $this->getFront()->getDefault('module'); $request->setAlias(Mage_Core_Model_Url_Rewrite::REWRITE_REQUEST_PATH_ALIAS, ''); } } if (!$module) { if (Mage::app()->getStore()->isAdmin()) { $module = 'admin'; } else { return false; } }
Next, the match
function will iterate through each of the available modules and try to match the controller and action using the following code:
… foreach ($modules as $realModule) { $request->setRouteName($this->getRouteByFrontName($module)); // get controller name if ($request->getControllerName()) { $controller = $request->getControllerName(); } else { if (!empty($p[1])) { $controller = $p[1]; } else { $controller = $front->getDefault('controller'); $request->setAlias( Mage_Core_Model_Url_Rewrite::REWRITE_REQUEST_PATH_ALIAS, ltrim($request->getOriginalPathInfo(), '/') ); } } // get action name if (empty($action)) { if ($request->getActionName()) { $action = $request->getActionName(); } else { $action = !empty($p[2]) ? $p[2] : $front->getDefault('action'); } } //checking if this place should be secure $this->_checkShouldBeSecure($request, '/'.$module.'/'.$controller.'/'.$action); $controllerClassName = $this->_validateControllerClassName($realModule, $controller); if (!$controllerClassName) { continue; } // instantiate controller class $controllerInstance = Mage::getControllerInstance($controllerClassName, $request, $front->getResponse()); if (!$controllerInstance->hasAction($action)) { continue; } $found = true; break; } ...
Now that looks like an awful lot of code! Let's break it down further. The first part of the loop will check if the request has a controller name. If it is not set, it will check our parameter array's ($p
) second value and try to determine the controller name. Then, it will try to do the same for the action name.
If we get this far in the loop, we should have a module name, a controller name, and an action name. Magento will now use these to try and get matched with the Controller class name by calling the following code:
$controllerClassName = $this->_validateControllerClassName($realModule, $controller);
This function will not only generate a matching class name, but it will also validate its existence. In our example case, this function should return Mage_Catalog_CategoryController
.
As we now have a valid class name, we can proceed to instantiate our controller object. You may probably notice that so far we haven't done anything with our action yet, and that's precisely the next step on our loop.
Now, our instantiated controller comes with a very handy function called hasAction()
. In essence, all this function does is call a PHP function called is_callable()
, which will check if our current controller has a public function matching the action name. In our case this will be viewAction()
.
The reason behind this elaborate matching process and the use of a foreach
loop is that it is possible for several modules to use the same frontName
:

Now, http://localhost/catalog/category/view/id/10
is not a very user-friendly URL. Fortunately, Magento has its own URL rewrite system that allows us to use http://localhost/books.html
.
Let's dig a little deeper into the URL rewrite system and see how Magento gets the controller and action names from our URL alias. Inside our Varien/Front.php
controller dispatch function, Magento will call the following action:
Mage::getModel('core/url_rewrite')->rewrite();
Before actually looking into the inner working of the rewrite function, let's take a look at the structure of the core/url_rewrite
model:
Array ( ["url_rewrite_id"] => "10" ["store_id"] => "1" ["category_id"] => "10" ["product_id"] => NULL ["id_path"] => "category/10" ["request_path"] => "books.html" ["target_path"] => "catalog/category/view/id/10" ["is_system"] => "1" ["options"] => NULL ["description"] => NULL )
As we can see, the rewrite module comprises several properties, but only two of them are of particular interest to us, namely request_path
and target_path
. Simply put, the job of the rewrite module is to modify the request object path information with the matching values of target_path
.
- 手機安全和可信應用開發(fā)指南:TrustZone與OP-TEE技術詳解
- 21天學通C++(第6版)
- Mastering Unity Shaders and Effects
- 深度強化學習算法與實踐:基于PyTorch的實現(xiàn)
- Java性能權威指南(第2版)
- Julia Cookbook
- 網絡爬蟲原理與實踐:基于C#語言
- 手把手教你學C語言
- JavaScript:Moving to ES2015
- Web Development with MongoDB and Node(Third Edition)
- Java 9 Programming By Example
- 大學計算機基礎實訓教程
- Anaconda數(shù)據(jù)科學實戰(zhàn)
- Python Web自動化測試設計與實現(xiàn)
- Java并發(fā)實現(xiàn)原理:JDK源碼剖析