ezSQL是由Justin Vincent开发的一个开源项目,现在已经用在超过10万的网站上,而且大名鼎鼎的博客程序WordPress的wpdb数据库类就是由ezSQL类继承而来的。ezSQL统一了几个使用频率非常高的函数接口,使得你能很简单的使用 mySQL, Oracle8, SQLite (PHP),mssql等各种数据库。ezSQL还提供了缓存机制和调试机制,再加上其面向对象的编程,可以有效的减少开发时间,提升开发速度。
第一次接触到ezSQL是在修改wordpress的代码的时候,但是当时由于比较忙于搞其它的功能开发就没有仔细深入的研究它了。这次吵吵想开发一款实验室信息管理系统,用以管理实验室的海量数据的时候,又想起了它,就去仔细的了解了以下它。
ezSQL是Github上的一个开源项目,目前最新的版本是2.17,它的主页是:https://github.com/jv2222/ezSQL
一个好的类库就是能让代码简洁而又使功能充分。我们往往赞叹windows api做的很好,一千多个API做的没有一个重复的,然而创造一个可用而又简洁的api其实往往比做十个不同的api来的更有意义。ezSQL重新设计了我们操作数据库的习惯,归纳的这几个API在使用频率上都超过99%了。
– $db->get_results – 从数据库库或者缓存中获取多行的数据。
– $db->get_row — 从数据库库或者缓存中获取一行数据。
– $db->get_col – 从数据库库或者缓存中获取一列数据。
– $db->get_var — 从数据库库或者缓存中的一行中获取一个变量。
– $db->query — 从数据库中执行一个query,如果有结果的话就缓存。
– $db->debug – 输出最后执行sql并获取的结果。
– $db->vardump – 输出所有的内容和结构。
– $db->select — 选择一个新的数据库。
– $db->get_col_info – 获取一列或者多列的所有信息。
使用的方法很简单,我们参考官方的例子就可以了,如果需要详细的资料可以查看官方的ez_sql_core.php文件。
/**********************************************************************
* ezSQL initialisation for mySQL
*/
// Include ezSQL core
include_once "../shared/ez_sql_core.php";
// Include ezSQL database specific component
include_once "ez_sql_mysql.php";
// Initialise database object and establish a connection
// at the same time - db_user / db_password / db_name / db_host
$db = new ezSQL_mysql('db_user','db_password','db_name','db_host');
/**********************************************************************
* ezSQL demo for mySQL database
*/
// Demo of getting a single variable from the db
// (and using abstracted function sysdate)
$current_time = $db->get_var("SELECT " . $db->sysdate());
print "ezSQL demo for mySQL database run @ $current_time";
// Print out last query and results..
$db->debug();
// Get list of tables from current database..
$my_tables = $db->get_results("SHOW TABLES",ARRAY_N);
// Print out last query and results..
$db->debug();
// Loop through each row of results..
foreach ( $my_tables as $table )
{
// Get results of DESC table..
$db->get_results("DESC $table[0]");
// Print out last query and results..
$db->debug();
}
?>
这篇日志到此似乎就要结束了,但是好不容易找到这样一个小型又优秀的类库,我们有理由硬着头皮来读读它的代码了,来看看它的设计思想,来借鉴一下它的架构。
1、设计思想
ezSQL将上文所讲的几个函数做成了一个类,就是ez_sql_core.php种的ezSQLcore类,该类抽象了如上文所讲的几个方法,如$db->get_row等,同时还有其缓存机制等。但是却没有涉及到不同数据库之间如mssql和mysql之间语法的差别,如mysql_query和mssql_query就是不同的。
那么它是如何忽略到了这种不同,而使得基类能够执行这些功能呢?往往我们的思维定式就是继承,我们继承基类的方法在子类中做些修改,使其来符合我们不同的需要。比如我用mysql做query,我就先继承基类,然后做重载query的方法修改成mysql_query来实现我们的需要,然而ezSQL在这里的设计让我惊叹了一回。
比如上文提到一个函数是get_var,即获取一个变量,但是我们跟踪这个函数就发现它返回的是$this->query($query)的结果,问题是我们在这个ezSQLcore类中并没有发现有query这个函数的定义啊,那么它如何能够执行呢?
转移到ez_sql_mysql.php文件中,我们发现ezSQL_mysql 继承于ezSQLcore,但是ezSQL_mysql却有了query这个方法,我们就恍然明白了:$this->query($query) 实际上到我们创建了ezSQL_mysql类之后,this指针指向的也就是子类ezSQL_mysql了,自然它就有了query这个方法。虽然这也可以看做是对query方法的重载,但是这种设计又给了我对于类和继承的一种新认识。
2、缓存机制
要了解它的缓存机制,我们看看这个存储缓存的函数store_cache就可以了,读取缓存亦然。
function store_cache($query,$is_insert)
{
// The would be cache file for this query
$cache_file = $this->cache_dir.'/'.md5($query);
// disk caching of queries
if ( $this->use_disk_cache && ( $this->cache_queries && ! $is_insert ) || ( $this->cache_inserts && $is_insert ))
{
if ( ! is_dir($this->cache_dir) )
{
$this->register_error("Could not open cache dir: $this->cache_dir");
$this->show_errors ? trigger_error("Could not open cache dir: $this->cache_dir",E_USER_WARNING) : null;
}
else
{
// Cache all result values
$result_cache = array
(
'col_info' => $this->col_info,
'last_result' => $this->last_result,
'num_rows' => $this->num_rows,
'return_value' => $this->num_rows,
);
file_put_contents($cache_file, serialize($result_cache));
if( file_exists($cache_file . ".updating") )
unlink($cache_file . ".updating");
}
}
}
概括起来它的所谓的缓存机制,就是将一个query按照md5加密后作为缓存文件的文件名生成这个缓存文件,然后将列信息、最后一次返回的结果以及行数生成一个数组result_cache,最后用serialize函数将这个数组中的数据串行化,使其成为一串有特定格式的字符串,并将保存在缓存文件中。
读取缓存则是判断缓存有效时间,如果在有效期内,就读取缓存文件,反串行化数据为一个数组,并返回结果。
使用缓存机制得到的效果是显而易见的,一是直接读取文件的速度要比查询数据库要快,二是可以有效的减缓数据库的压力。但是滥用缓存的后果也是严重的,因为你要定期的去清理这些缓存文件。此外,如果是一些需要实时更新的数据,缓存机制也无用武之地。所以最好的做法还是对使用频率高而且不要求实时更新的SQL查询做缓存,对于使用频率低的sql就不要再缓存了,直接数据库查一下吧。
3、调试机制
其实这个机制也没什么可说的,大家可以看debug函数就好了,无非就是用了一个last_error详细记录了错误信息,包括是哪个查询语句产生的等等。
其中用到了php输出缓存机制,它能允许你更加灵活的控制输入输出,特别是当你想在数据已经输出后,再输出文件头的情况。因为使用了php输出缓存机制其顺序就有所改变了:
1.打开了php输出缓存: echo,print -> php output_buffring -> server buffering -> browser buffering -> browser display
2.未打开php输出缓存: echo,print -> server buffering -> browser buffering -> browser display
php的输出缓存还可以用来做一些在线聊天的功能,以及缓存页面的功能。比如我们可以将首页的输出缓存为一个HTML文件,用户访问我们的网站的时候调用缓存页面,就可以很大程度上减轻网站的压力。
好了,这篇文章就到此为止了。最后,我们再总结一下:
1、最好的程序员修炼之道是读别人的代码。
2、最优秀的程序设计,重在“设计”。
如无特别说明,本博客文章皆为原创。转载请说明,来自吵吵博客。
吵吵微信朋友圈,请付款实名加入: