点击数:12622015-07-29 15:41:12 来源: 外贸网站建设,深圳外贸网站建设,深圳网站建设,外贸商城网站制作-亿恩科技
在Magento跟目录下的.htaccess文件中有如下配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
<IfModule mod_rewrite.c>
############################################
## enable rewrites
Options +FollowSymLinks
RewriteEngine on
############################################
## always send 404 on missing files in these folders
RewriteCond %{REQUEST_URI} !^/(media|skin|js)/
############################################
## never rewrite for existing files, directories and links
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
############################################
## rewrite everything else to index.php
RewriteRule .* index.php [L]
</IfModule>
|
根据配置可知,当访问media|skin|js目录中不存在的页面文件时,httpd(Apache)将返回自身404设置,一般都是一个白底黑字的说明。可以修改默认处理:
1
2
3
4
5
6
7
8
|
// httpd
ErrorDocument 404 404.html
ErrorDocument 403 403.html
// nginx
fastcgi_intercept_errors on;
error_page 404 404.html;
error_page 403 403.html;
|
针对Nginx的Magento配置,参考:http://www.vfeelit.com/175.html
除了http服务的默认404处理,Magento本身也会可能做出404响应,查看Mage:run()方法代码:
1
2
3
4
5
6
7
8
9
10
11
|
public static function run($code = '', $type = 'store', $options = array())
{
try {
// throw new Mage_Core_Model_Store_Exception('');
} catch (Mage_Core_Model_Session_Exception $e) {
} catch (Mage_Core_Model_Store_Exception $e) {
require_once(self::getBaseDir() . DS . 'errors' . DS . '404.php');
die();
} catch (Exception $e) {
}
|
当捕捉到Mage_Core_Model_Store_Exception异常时,会返回errors/404.php页面,在try中主动抛出这个异常(以上代码注释部分),看看结果:
实际上它直接把error目录下的404.php作为模板返回,具体细节就不在这里讨论了。不过比较感兴趣的是,这个异常是怎么被抛出的,在什么地方?我们可以直接搜索Mage_Core_Model_Store_Exception类,最终是在App的getStore方法中找到:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
public function getStore($id = null)
{
if (!Mage::isInstalled() || $this->getUpdateMode()) {
return $this->_getDefaultStore();
}
if ($id === true && $this->isSingleStoreMode()) {
return $this->_store;
}
if (!isset($id) || ''===$id || $id === true) {
$id = $this->_currentStore;
}
if ($id instanceof Mage_Core_Model_Store) {
return $id;
}
if (!isset($id)) {
$this->throwStoreException();
}
if (empty($this->_stores[$id])) {
$store = Mage::getModel('core/store');
/* @var $store Mage_Core_Model_Store */
if (is_numeric($id)) {
$store->load($id);
} elseif (is_string($id)) {
$store->load($id, 'code');
}
if (!$store->getCode()) {
$this->throwStoreException();
}
$this->_stores[$store->getStoreId()] = $store;
$this->_stores[$store->getCode()] = $store;
}
return $this->_stores[$id];
}
|
如果无法取得店铺Id或者获取了Id但是无法根据Id获取店铺代码,这个异常就会被抛出,如果是这个情况那就是这个店铺根本不存在,访问的店铺都不存在自然要返回404了。不过由于Magento的逻辑,一般还不容易遇到这个页面返回。
接下来探讨Magento的第二种404,也是最常见的。可以参考http://blog.ifeeline.com/470.html了解Magento的路由过程。对于不存在frontName,控制器和action方法,一般都会路由到cms/index/noRoute(默认是这样,后台可配置),以下是default路由器的match方法,它展示了如何实现这个noRoute:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
public function match(Zend_Controller_Request_Http $request)
{
$noRoute = explode('/', Mage::app()->getStore()->getConfig('web/default/no_route'));
/*
<default>
<cms_home_page>home</cms_home_page>
<cms_no_route>no-route</cms_no_route>
<cms_no_cookies>enable-cookies</cms_no_cookies>
<front>cms</front>
<no_route>cms/index/noRoute</no_route>
<show_cms_breadcrumbs>1</show_cms_breadcrumbs>
</default>
模块名被修改为了CMS 对应index控制器 和 noRoute方法,noRoute方法就是处理404返回的逻辑
*/
$moduleName = isset($noRoute[0]) ? $noRoute[0] : 'core';
$controllerName = isset($noRoute[1]) ? $noRoute[1] : 'index';
$actionName = isset($noRoute[2]) ? $noRoute[2] : 'index';
if (Mage::app()->getStore()->isAdmin()) {
$adminFrontName = (string)Mage::getConfig()->getNode('admin/routers/adminhtml/args/frontName');
if ($adminFrontName != $moduleName) {
$moduleName = 'core';
$controllerName = 'index';
$actionName = 'noRoute';
Mage::app()->setCurrentStore(Mage::app()->getDefaultStoreView());
}
}
$request->setModuleName($moduleName)
->setControllerName($controllerName)
->setActionName($actionName);
return true;
}
|
从web/default/no_route配置(后台可配置)中获取cms/index/noRoute,对应填入模块名,控制器名和action名,很明显,如果没有找到就使用Mage_Cms_IndexController控制器的noRoute方法来处理:
1
2
3
4
5
6
7
8
9
10
|
public function noRouteAction($coreRoute = null)
{
$this->getResponse()->setHeader('HTTP/1.1','404 Not Found');
$this->getResponse()->setHeader('Status','404 File not found');
$pageId = Mage::getStoreConfig(Mage_Cms_Helper_Page::XML_PATH_NO_ROUTE_PAGE);
if (!Mage::helper('cms/page')->renderPage($this, $pageId)) {
$this->_forward('defaultNoRoute');
}
}
|
Mage_Cms_Helper_Page::XML_PATH_NO_ROUTE_PAGE的值为web/default/cms_no_route,一般配置应该为no-route,接着就渲染这个no-route页面。这里先去后台看看配置:
接着进入Cms的Page:可以看到,这个404页面就是一个Cms Page,可以在这里进行随意修改定制。回到代码,万一没有为roRoute指定页面,那么就调用defaultNoRoute来处理:
1
2
3
4
5
6
7
8
|
public function defaultNoRouteAction()
{
$this->getResponse()->setHeader('HTTP/1.1','404 Not Found');
$this->getResponse()->setHeader('Status','404 File not found');
$this->loadLayout();
$this->renderLayout();
}
|
可看到,它直接渲染输出:
可以看到,这个404页面就是一个Cms Page,可以在这里进行随意修改定制。回到代码,万一没有为roRoute指定页面,那么就调用defaultNoRoute来处理:
1
2
3
4
5
6
7
8
public function defaultNoRouteAction()
{
$this->getResponse()->setHeader('HTTP/1.1','404 Not Found');
$this->getResponse()->setHeader('Status','404 File not found');
$this->loadLayout();
$this->renderLayout();
}
可看到,它直接渲染输出:
注意看,它还是输出了一句话,这个defaultNoRoute方法实际应用了cms.xml配置中的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<cms_index_noroute translate="label">
<label>CMS No-Route Page</label>
</cms_index_noroute>
<cms_index_defaultnoroute>
<remove name="right"/>
<remove name="left"/>
<reference name="root">
<action method="setTemplate"><template>page/1column.phtml</template></action>
</reference>
<reference name="content">
<block type="core/template" name="default_no_route" template="cms/default/no-route.phtml"/>
</reference>
</cms_index_defaultnoroute>
|
cms_index_defaultnoroute的句柄配置,它应用了1column.phtml布局,然后在content中添加一个子块,这个子块对应cms/default/no-route.phtml模板,这个模板中只有“There was no 404 CMS page configured or found.”这段文本。
如果不想用Cms的页面,那么就可以自定义这个默认的模板获取一个友好的404页面输出。甚至,可以不使用Cms模块提供的noRroute方法,比如你希望使用一个自定义的模块来处理No Route页面以实现比较复杂的逻辑,那么可以在后台修改Default No-route URL的设置,这个设置会影响到Default路由器的赋值。