之前总是以脚本面向过程的方式写 PHP 代码,所以很大程度上来说,既不规范,也不安全,更不容易维护。为了代码的重用,准备写一套自己的工具库,这样的话,以后写项目的时候就可以很轻松的进行使用啦。
今天要进行实现的是一个数据库连接池,以配置文件的方式来实现。
XML 作为一门高可用的结构化语言,作为配置文件真的是言简意赅,虽然相比于近来配置文件界的 YAML, JSON 等翘楚来说,可能有效数据的占比比较小,但是这种冗余是有其存在的价值的。
基本上,看完 xml 的节点就可以知道其功能。这也是为什么大项目都会使用 XML 作为配置文件的原因。
在 PHP 中,使用 XML 文件会是一件赏心悦目的事情,虽然相对于 Java 程序而言,如此。但是相比于 Python 处理,PHP 程序就显得没有那么优雅了。
读取配置文件其实说白了就是对文件的读取,然后包装一下。我常用的有如下两种方式。
第一次使用这个简易方式的时候,真的是有点郁闷。
- $content = file_get_contents("filename.xml");
- echo $content;
结果使用浏览器访问这个测试用的 php 文件时,却只显示了 xml 的内容部分,但是节点信息什么的根本没有显示。
然后我还特地查阅了一下帮助文档,这个函数返回的结果是字符串无疑的啊。然后 vardump 之后也证明了这一点。于是也没有多想,还以为这种方式能自动的过滤掉 XML 的标签 TAG 信息呢。
最后一个偶然的测试,打开了网页源代码,发现这个函数确实读到了 XML 的所有信息,只不过显示在浏览器上就会被浏览器给自动解析了。所以只能看到相关的内容部分。
常规方式就是按部就班的读取文件了。其余的话和上述方案一致。
- // 读取配置文件内容
- $handle = fopen("filepath", "r");
- $content = fread($handle, filesize("filepath"));
上述两种读取文件,其实都是为了 PHP 解析 XML 来做准备的。关于 PHP 解析 XML 的方式的博客有很多。方式也有很多,像 simplexml,XMLReader,DOM 啦等等。但是对于比较小型的 xml 配置文件,simplexml 就足够了。
- <?xml version="1.0" encoding="UTF-8" ?>
- <mysql>
- <!-- 为防止出现意外,请按照此标准顺序书写.其实也无所谓了 -->
- <host>
- localhost
- </host>
- <user>
- root
- </user>
- <password>
- 123456
- </password>
- <db>
- test
- </db>
- <port>
- 3306
- </port>
- </mysql>
- <?php
- /**
- * 作为解析XML配置文件必备工具
- */
- class XMLUtil {
- public static $dbconfigpath = "./db.config.xml";
- public static function getDBConfiguration() {
- $dbconfig = array ();
- try {
- // 读取配置文件内容
- $handle = fopen(self::$dbconfigpath, "r");
- $content = fread($handle, filesize(self::$dbconfigpath));
- // 获取xml文档根节点,进而获取相关的数据库信息
- $mysql = simplexml_load_string($content);
- // 将获取到的xml节点信息赋值给关联数组,方便接下来的方法调用
- $dbconfig['host'] = $mysql->host;
- $dbconfig['user'] = $mysql->user;
- $dbconfig['password'] = $mysql->password;
- $dbconfig['db'] = $mysql->db;
- $dbconfig['port'] = $mysql->port;
- // 将配置信息以关联数组的形式返回
- return $dbconfig;
- } catch ( Exception $e ) {
- throw new RuntimeException ( "<mark>读取数据库配置文件信息出错!</mark><br />" );
- }
- return $dbconfig;
- }
- }
对于 PHP 程序而言,优化永无止境。而数据库连接池就在一定程度上起到了优化的作用。其使得对用户的每一个请求而言,无需每次都像数据库申请链接资源。而是通过已存在的数据库连接池中的链接来返回,从时间上,效率上,都是一个大大的提升。
于是,这里简单的模拟了一下数据库连接池的实现。核心在于维护一个 "池"。
- /**x
- * PHP中的数据库 工具类设计
- * 郭璞
- * 2016年12月23日
- *
- **/
- class DbHelper {
- private $dbconfig;
- private $dbpool;
- public $poolsize;
- public
- function __construct($poolsize = 20) {
- if (!file_exists("./utils.php")) {
- throw new RuntimeException("<mark>utils.php文件丢失,无法进行配置文件的初始化操作!</mark><br />");
- } else {
- require'. / utils.php';
- }
- // 初始化 配置文件信息
- $this - >dbconfig = XMLUtil: :getDBConfiguration();
- // 准备好数据库连接池"伪队列"
- $this - >poolsize = $poolsize;
- $this - >dbpool = array();
- for ($index = 1; $index <= $this - >poolsize; $index++) {
- $conn = mysqli_connect($this - >dbconfig['host'], $this - >dbconfig['user'], $this - >dbconfig['password'], $this - >dbconfig['db']) or die("<mark>连接数据库失败!</mark><br />");
- array_push($this - >dbpool, $conn);
- }
- }
- /**
- * 从数据库连接池中获取一个数据库链接资源
- *
- * @throws ErrorException
- * @return mixed
- */
- public
- function getConn() {
- if (count($this - >dbpool) <= 0) {
- throw new ErrorException("<mark>数据库连接池中已无链接资源,请稍后重试!</mark>");
- } else {
- return array_pop($this - >dbpool);
- }
- }
- /**
- * 将用完的数据库链接资源放回到数据库连接池
- *
- * @param unknown $conn
- * @throws ErrorException
- */
- public
- function release($conn) {
- if (count($this - >dbpool) >= $this - >poolsize) {
- throw new ErrorException("<mark>数据库连接池已满</mark><br />");
- } else {
- array_push($this - >dbpool, $conn);
- }
- }
- }
在申请数据库连接小于 20 的时候,程序直接从数据库连接池中获取。
当申请的数据库链接资源大于数据库连接池的上限时,不予提供。并提示异常。
当数据库连接池内已满的时候,如果想回首自定义的数据库链接资源,则不予支持,并报错提示。
回顾一下,本次试验主要是以面向对象的角度,设计并实现了一个简易的数据库连接池。在一定程度上对 PHP 代码的优化起到了作用。
另外简单的使用了 simplexml 对于 XML 文件的解析处理, 以及常用的对于文件读取的操作。
来源: