1. 程式人生 > >URL重寫原理,步驟 url rewrite

URL重寫原理,步驟 url rewrite

url: 轉載地址:http://www.magento-tutorial.net/how-does-magento-url-rewriting-work/ January 5th 2011 | Posted by admin

 Create a category

We just input the category's name, and set "is active" to Yes, and then click Save Category

We can see that the URL key is automaticly generated. The value is "nikon-camera".

When a category is created, in database table core_url_rewriting , there is a new record created at the same time

As we can see above, the main fields of table core_url_rewriting are:

  • Category_id (if this filed is null, it means this is a product url rewriting record)
  • Product_id (if this field is null, it means this is a category url rewriting record)
  • Id_path
  • Request_path (this is the url suffix which we will use in category page or product page)
  • Target_path (this is the real target url, it is the standard MVC style)

In front end of Magento, when we put mouse on the category we created

We can see the target url is looks like:

We are sure that the links of this menu is related with the database table core_url_rewriting, it is generated by the field request_path. Click on the category link, and then the category "Nikon" is opened.

How does Magento find the category by this URL?

1st stop: /index.php (this is the entrance of most part of URL request in Magento)

2nd stop: /app/Mage.php -> Mage::run()

3rd stop: Mage_Core_Controller_Varien_Front->dispatch()

All of things are handled in front controller’s dispatch() function, so let’s go inside of this function.

Here is source code of dispatch method, in order to see the main operation; we removed the line about Varien_Profiler, which is used to check programs performance.

Request is a global variable which contain all information about browser request, it is an object of class “Mage_Core_Controller_Request_Http ” which is extend from class Zend_Controller_Request_Http , here is the hierarchy diagram:

1. Rewriting

At the begining of dispatch(), browser request url “/nikon-camera.html" must be stored in request object. We can proof this by adding trace log to print the value $request->getPathInfo() .

It will print the value of request object’s attribute _pathInfo, here is the value at that moment:

/Nikon-camera.html

And then, below program is executed:

Mage::getModel('core/url_rewrite')->rewrite();

What this line did is modify the global request object, it will use function rewrite() of model class Mage_Core_Model_Url_Rewrite , this class is the entity object correspond with database table core_url_rewrite . Here is the last lines of the rewrite() method

We added trace log to see what is set into $request object, the printed result is:

Request URI = /index.php/catalog/category/view/id/7

Path info = catalog/category/view/id/7

At this moment, the url translation between browser request url and target url has been finished.

We guess that there must be a database operation before this, let’s look at the beginning source line of function rewrite().

$requestCases is an array which composed of $requestPath and $requestPath + $queryString.

As we can see in first highlight line, $requestPath is come from $request->getPathInfo(), as we have said before, this value is “/Nikon-camera.html”, after trimming, the value will become to “Nikon-camera.html”.

Let’s have a look what’s inside the function loadByRequestPath($path) , here is the function’s source:

The meaning of this function can be explained in one SQL:

Select * from core_url_rewrite where request_path = “$pathInfo”

As we talked before, the record has already created in database table core_url_rewrite when a category is created, so if the parameter $pathInfo can be found in database, then the entity object of Mage_Core_Model_Url_Rewrite will be initialized after above function executed. It means we can use below functions to get information of database table core_url_rewrite.

$this->getIdPath()

$this->getRequestPath()

$this->getTargetPath()

1. Matching

As we can see in diagram 1-6, there is a foreach operation

foreach ($this->_routers as $router) {

if ($router->match($this->getRequest())) {

break;

}

}

From here, the responsibility transfers to the front controller and router. The front controller has an array of “routers” that it uses to decide which module the URL should trigger. This correlation between URL and module name is defined in the config.xml files.

The available routers are:

• Standard (used in front end request)

• Admin (used in back office request)

• Default (only used for 404s)

The definition of a match between a router and a module looks like this for the Catalog module:

Before dispatch() function, there is an init() function calling which will initial the attribute $this->_routers. Each router will collect all modules information from all config.xml files, standard router (Mage_Core_Controller_Varien_Router_Standard ) will collect all frontend modules info and admin router (Mage_Core_Controller_Varien_Router_Admin ) will collect all backend modules info.

Let’s have a look what has been done in match() function of router, just for the sample, we put the standard router’s source her

By the pink comments, we can quick overview of the business logic of match() function.

  1. Analyzing target URL, purpose of this is:

a) Get module name

b) Get controller name

c) Get action name

  1. Instantiate controller class
  2. Set values to $request (module name, controller name, action name, other parameters)
  3. Dispatch action

We can add trace log to see each variable’s value, here they are:

$module = ‘catalog’

$realModule = ‘Mage_Catalog’

$controller = ‘category’

$ controllerClassName = ‘Mage_Catalog_CategoryController’

$action = ‘view’

$request->getParams() = Array

(

[id] => 7

)

After the last line executed in match() function, the responsibility will transfer to a specific controller to finish the left business logic. After business logic is finished, there is a result page will be rendered and be set into response object. As we can see in diagram 1-6, the last line in dispatch():

$this->getResponse()->sendResponse();

After this, the result page will be sent to client browser. That’s all.