您好,欢迎来到六安矩阵网络一站式互联网营销服务平台!
咨询邮箱: service@matrixcn.com 咨询热线:13516498856

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
上一篇:opencart全面伪静态方法
下一篇:直接恢复DEDE(织梦系统)网站备份数据
通话
短信
留言
首页