文档章节

PHP防止一次请求多次调用同一函数或方法重复查询数据库的方法

 零度开水
发布于 2017/01/16 11:53
字数 1143
阅读 126
收藏 0

在PHP开发中,为了实现需求或者因为代码质量,难免会出现在一次请求中多次调用同一函数或类方法。如果在这一函数或者类方法中需要查询数据库,多次调用时就会多次查询数据库。如果这多次查询结果还是一样的,就会造成服务器资源浪费,节约这部分被浪费的资源,在并发量大或者服务器配置低的情况下就很有用。

例如,在开发用户相关模块时定义了一个获取用户信息的函数:

function GetUserInfo($id) {
	/* 此处省略数据库相关初始化 */
	$user_info = $db->getRow($sql);
	if (!is_array($user_info)) {
		$user_info = array();
	}
	return $user_info;
}

在请求开始时是初始化文件中,先获取当前登录用户信息:

$current_user = GetUserInfo($_SESSION['user_id']);
if (!$current_user) {
	/* ...... */
} else {
	/* ...... */
}

在实际处理文件中,可能再次或多次通过GetUserInfo函数获取当前登录用户信息,甚至在模板里面一次或多次通过GetUserInfo函数获取当前登录用户信息。

在这种情况下,用户信息基本上没有变动,也很少出现在一次请求中,开头和结尾的当前用户信息不一样的情况,那调用了GetUserInfo函数几次,就几次打开、查询、关闭数据库。再多定义几个这种类似的函数和多次调用,那就又多次打开、查询、关闭数据库。

如何避免这种情况呢?这就要用到static(静态变量)。

静态变量仅在局部函数域中存在且只被初始化一次,当程序执行离开此作用域时,其值不会消失,会使用上次执行的结果。一般的函数内变量在函数结束后会释放,比如局部变量,但是静态变量却不会。也就是说,下次再调用这个函数的时候,该变量的值会保留下来。

那我们将GetUserInfo函数改一下:

function GetUserInfo($id) {
	static $users = array();
	if (isset($users[$id])) {
		return $users[$id];
	}
	/* 此处省略数据库相关初始化 */
	$user_info = $db->getRow($sql);
	if (!is_array($user_info)) {
		$user_info = array();
	}
	$users[$id] = $user_info;
	return $user_info;
}

这样的话,在一次请求当中,获取过的用户信息都会保留在内存中,直到本次请求完成或关闭。即使多次调用GetUserInfo函数获取同一用户信息,就会先判断是否已经查询过这个用户,如果已经查询过一次,就直接返回上次查询出来的信息。

上面举的例子看起来有点像面向过程的写法,实际上,面向对象的写法也是差不多的。

比如,定义了这么几个类:

class AClass {
	
	public function __construct() {
		$user = $this->GetUserInfo($_SESSION['user_id']);
		/* 接下来做了用户数据处理 */
	}
	
	protected function GetUserInfo($id) {
		/* 此处省略数据库相关初始化 */
		$user_info = $db->getRow($sql);
		if (!$user_info) {
			$user_info = array();
		}
		return $user_info;
	}
	
}

class BClass extends AClass {
	
	public function __construct() {
		parent::__construct();
		$user = $this->GetUserInfo($_SESSION['user_id']);
		/* 接下来因为需求原因,重新做用户数据处理 */
	}
	
}

class CClass extends BClass {
	
	public function __construct() {
		parent::__construct();
		$user = $this->GetUserInfo($_SESSION['id']);
		/* 接下来因为使用场景,又要重新做用户数据处理 */
	}
	
	public function index() {
		$user = $this->GetUserInfo($_SESSION['id']);
		/* 接下来又做了一次用户数据处理,在模板里面使用 */
		$this->display('index.html');
	}
	
}

同样的,我们将AClass中的GetUserInfo方法改一下:

class AClass {
	
	public function __construct() {
		$user = $this->GetUserInfo($_SESSION['user_id']);
		/* 接下来做了用户数据处理 */
	}
	
	protected function GetUserInfo($id) {
		static $users = array();
		if (isset($users[$id])) {
			return $users[$id];
		}
		/* 此处省略数据库相关初始化 */
		$user_info = $db->getRow($sql);
		if (!$user_info) {
			$user_info = array();
		}
		$users[$id] = $user_info;
		return $user_info;
	}
	
}

也同样解决了重复查询数据库的问题。

各位看官不要觉得这样写很搞笑,在实际开发中是会出现这种情况的,尤其是对于新手来说。本着学习的态度,大家相互讨论,共同进步,欢迎吐槽。

© 著作权归作者所有

粉丝 3
博文 1
码字总数 1143
作品 0
南宁
私信 提问

暂无文章

关于AsyncTask的onPostExcute方法是否会在Activity重建过程中调用的问题

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/XG1057415595/article/details/86774575 假设下面一种情况...

shzwork
今天
6
0
object 类中有哪些方法?

getClass(): 获取运行时类的对象 equals():判断其他对象是否与此对象相等 hashcode():返回该对象的哈希码值 toString():返回该对象的字符串表示 clone(): 创建并返此对象的一个副本 wait...

happywe
今天
6
0
Docker容器实战(七) - 容器中进程视野下的文件系统

前两文中,讲了Linux容器最基础的两种技术 Namespace 作用是“隔离”,它让应用进程只能看到该Namespace内的“世界” Cgroups 作用是“限制”,它给这个“世界”围上了一圈看不见的墙 这么一...

JavaEdge
今天
8
0
文件访问和共享的方法介绍

在上一篇文章中,你了解到文件有三个不同的权限集。拥有该文件的用户有一个集合,拥有该文件的组的成员有一个集合,然后最终一个集合适用于其他所有人。在长列表(ls -l)中这些权限使用符号...

老孟的Linux私房菜
今天
7
0
面试套路题目

作者:抱紧超越小姐姐 链接:https://www.nowcoder.com/discuss/309292?type=3 来源:牛客网 面试时候的潜台词 抱紧超越小姐姐 编辑于 2019-10-15 16:14:56APP内打开赞 3 | 收藏 4 | 回复24 ...

MtrS
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部