- Opencart使用伪静态时会造成大量数据库调用的问题
- 点击次数 | 更新时间 | 2016-04-15 23:22:59
-
[摘要] Opencart是一套还不错的商场系统,特别是其模块化的设计思路。这是我在刚接触Opencart后的初步印象,另外在深入了解Opencart的源代码之后,我觉得Opencart还是一个很不错的入门框架。现在的大型框架...
Opencart是一套还不错的商场系统,特别是其模块化的设计思路。这是我在刚接触Opencart后的初步印象,另外在深入了解Opencart的源代码之后,我觉得Opencart还是一个很不错的入门框架。现在的大型框架比如YII,LARAVEL以及ZEND等,都是把程序源代码写得让一般人看不了,进入的入口页写得很简单,一般两句就几句,定义个报错模式,然后就加载个应用,再执行一下应用init之类或是boot函数驱动整个Application,让人望而生畏。而Opencart则相对较简单,但又精致地体现了当前主流框架的思路。
不过今天我在这里想讲的是Opencart在使用伪静态后频繁调用数据库的问题,先说一下Opencart在伪静态的情况下进入页面时真实URL是:index.php?_route_=(模块/)控制器/方法&参数名=参数值...。这个最终会通过catolog/controller/common/seo_url.php进行解析处理,代码如下:
class ControllerCommonSeoUrl extends Controller { public function index() { // Add rewrite to url class if ($this->config->get('config_seo_url')) { $this->url->addRewrite($this); } // Decode URL if (isset($this->request->get['_route_'])) { $parts = explode('/', $this->request->get['_route_']); // remove any empty arrays from trailing if (utf8_strlen(end($parts)) == 0) { array_pop($parts); } foreach ($parts as $part) { $query = $this->db->query("SELECT * FROM " . DB_PREFIX . "url_alias WHERE keyword = '" . $this->db->escape($part) . "'"); if ($query->num_rows) { $url = explode('=', $query->row['query']); if ($url[0] == 'product_id') { $this->request->get['product_id'] = $url[1]; } if ($url[0] == 'category_id') { if (!isset($this->request->get['path'])) { $this->request->get['path'] = $url[1]; } else { $this->request->get['path'] .= '_' . $url[1]; } } ..... }
可以看到对路由分析时会查询数据库查询控制器和action方法(在此之前会调用system/engine/action判断模块),路径解析当然只有一次调用,所以这里不会产生多次调用url_alias 的情况,但是catolog/controller/common/seo_url.php里另一个生成伪静态的方法却是主要因素,方法如下:
public function rewrite($link) { $url_info = parse_url(str_replace('&', '&', $link)); $url = ''; $data = array(); parse_str($url_info['query'], $data); foreach ($data as $key => $value) { if (isset($data['route'])) { if (($data['route'] == 'product/product' && $key == 'product_id') || (($data['route'] == 'product/manufacturer/info' || $data['route'] == 'product/product') && $key == 'manufacturer_id') || ($data['route'] == 'information/information' && $key == 'information_id')) { $query = $this->db->query("SELECT * FROM " . DB_PREFIX . "url_alias WHERE `query` = '" . $this->db->escape($key . '=' . (int)$value) . "'"); if ($query->num_rows) { $url .= '/' . $query->row['keyword']; unset($data[$key]); } } elseif ($key == 'path') { $categories = explode('_', $value); foreach ($categories as $category) { $query = $this->db->query("SELECT * FROM " . DB_PREFIX . "url_alias WHERE `query` = 'category_id=" . (int)$category . "'"); if ($query->num_rows) { $url .= '/' . $query->row['keyword']; } else { $url = ''; break; } } unset($data[$key]); } elseif ($key == 'route' && $value == 'common/home') { $url = '/'; } } } if ($url) { unset($data['route']); $query = ''; if ($data) { foreach ($data as $key => $value) { $query .= '&' . rawurlencode((string)$key) . '=' . rawurlencode((string)$value); } if ($query) { $query = '?' . trim($query, '&'); } } return $url_info['scheme'] . '://' . $url_info['host'] . (isset($url_info['port']) ? ':' . $url_info['port'] : '') . str_replace('/index.php', '', $url_info['path']) . $url . $query; } else { return $link; } }
可以看到,在每次执行生成一个URL时,Opencart都会调用这个函数查询一次数据库。
$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "url_alias WHERE `query` = '" . $this->db->escape($key . '=' . (int)$value) . "'");
有一种情况我们肯定经常碰到, 一个数据循环展示的时候,会在展示中添加点击的链接,而这个链接需要调用上面的URL进行伪静态处理,而每次调用都会产生一次数据库调用,像这样就会产生上百次数据库调用,造成性能极大下滑。想我在使用OPENCART时打印出Opencart的MYSQL查询记录列表,看到几百次调用url_alias时我真是醉了。
知道了问题所在,解决的方法也很简单,如是这个页面调用的URl会是很多,比如类目伪静态化会调用url_alias表中很多数据,可以直接把表数据一次性读取出来,如果调用的次数多,但基本都是一个链接,可以从表中读取并保存到数组中,下次再调用时判断是否已有此数据。
- 上一篇:opencart全面伪静态方法
- 下一篇:直接恢复DEDE(织梦系统)网站备份数据