今天早上才发表了一篇,下午paperen我趁着有空又回头去看了下个phpcms的代码,一直看到晚上,当然啦,这次再看又有了不少收获,有些地方理解更加深刻了,或许paperen说的学习php的好办法就是在动手与读代码中循环进行的。?

不说太多废话了吧,这次挖了它操作mysql的那个类过来解剖,这个类用起来还真是相当的方便啊。让我们来see see到底是怎样使用吧。不过在你看下面的东西时先声明一下单这个类的代码就有240多行。paperen我会在下面慢慢说的。?

一开始肯定要定义一系列数据库相关的常量与require这个文件过来。

201003061267886225

之后就创建一个对象,然后调用connect方法去连接我们的mysql数据库。

201003061267886342

?到这里先让大家看看这个类中的connect方法是怎样的吧。(代码不少)

function connect($dbhost, $dbuser, $dbpw, $dbname = '', $pconnect = 0, $charset = '')
?{
??$func = $pconnect == 1 ? 'mysql_pconnect' : 'mysql_connect';//选择连接mysql是否持久连接(而两者的区别我也是不太明白)
??if(!$this->connid = @$func($dbhost, $dbuser, $dbpw))
??{
???if(DB_NAME == '' && file_exists(PHPCMS_ROOT.'install.php'))
???{
????header('location:./install.php');//对于数据库名字为空的话会跳转到安装那,如果自己挖过来用的话,需要改改这里啦
????exit;
???}
???$this->halt('Can not connect to MySQL server');//用自身的halt方法报错
???return false;
??}
??if($this->version() > '4.1')
??{
???$serverset = $charset ? "character_set_connection='$charset',character_set_results='$charset',character_set_client=binary" : '';
???$serverset .= $this->version() > '5.0.1' ? ((empty($serverset) ? '' : ',')." sql_mode='' ") : '';
???$serverset && mysql_query("SET $serverset", $this->connid);//这里大概是设置送入数据库的字符编码吧
??}
??if($dbname && !@mysql_select_db($dbname , $this->connid))
??{
???$this->halt('Cannot use database '.$dbname);//选择数据库,选不上也报错
???return false;
??}
??$this->dbname = $dbname;//将能选择上的数据库名字赋予类中的dbname变量
??return $this->connid;//返回连接标识号
?}

都已经写上注释了,希望大家能看明白吧,不过这个connect方法其实也不需要大家看懂吧,会用上就行啦。主要是要设置对我们的常量DB_HOST,DB_USER等等。不然会出现一些错误。?

再来看看query方法,其实就是与mysql_query差不多不错多了可以选择两种输入sql语句的方法并且还有自定义报错功能的支持。

function query($sql , $type = '')
?{
??$func = $type == 'UNBUFFERED' ? 'mysql_unbuffered_query' : 'mysql_query';//选择不同的送入sql语句的方式,后者我都没用过……
??if(!($query = @$func($sql , $this->connid)) && $type != 'SILENT')//送入sql语句加判断
??{
???$this->halt('MySQL Query Error', $sql);//如果失败则报错
???return false;
??}
??$this->querynum++;//没送入一条自身的querynum变量加1
??return $query;//返回mysql返回的数据标识集(是这样叫吧,这个东西不是数据)
?}

对于用法很简单啦,echo $db->query("select * from member");//会得到类似Resource id #4的结果,这就是paperen我说的这个并不是数据的自身,而是mysql给的一个标识吧(这样的结果也确实会令人不解)。?

之后是select方法。

function select($sql, $keyfield = '')//注意参数都有些什么,别传错值了
?{
??$array = array();
??$result = $this->query($sql);//调用query方法得到那个数据标识集
??while($r = $this->fetch_array($result))//fetch_array其实就是mysql_fetch_array
??{
???if($keyfield)//可以针对某个字段进行查数据
???{
????$key = $r[$keyfield];
????$array[$key] = $r;
???}
???else//否则将所有的数据都放到这个数组中
???{
????$array[] = $r;
???}
??}
??$this->free_result($result);//释放掉这个结果,这个方法其实就是mysql_free_result
??return $array;//返回这个数组
?}

使用起来真的很方便,例如没有加限定字段的查询 print_r($db->select("select name from member"));得到的结果数据的组织形式是类似这样的

Array ( [0] => Array ( [name] => paper ) [1] => Array ( [name] => liang ) [2] => Array ( [name] => tom ) [3] => Array ( [name] => peter ) )?

可能你还需要使用foreach对其进行分离。而对加上字端限制的,例如

foreach($db->select("select name from member where id=1","name") as $name=>$data){
??echo $name;
?}

应该就能符合你的要求,看你需要怎样处理数据吧,返回的反正是个数组,你根据自己需要进行一系列的分割就可以了。?

insert方法

function insert($tablename, $array)
?{
??$this->check_fields($tablename, $array);
??return $this->query("INSERT INTO `$tablename`(`".implode('`,`', array_keys($array))."`) VALUES('".implode("','", $array)."')");
?}

这个代码少而且很妙,参数的形式显而易见,对于插入的数据只要组织成一个数组形式然后放入来就可以了使用implode对数据进行分割还有array_keys,使各个数据都切到好处地形成一句标准的insert语句。(但是遗憾的是不支持多条数据的插入)?

使用方法是:

$array=array('name'=>'test','phone'=>'2232323223','email'=>'test@163.com');
?echo $db->insert("member",$array);?

get_fields方法(为了后面的方法的解析作个铺垫)

function get_fields($table)
?{
??$fields = array();
??$result = $this->query("SHOW COLUMNS FROM $table");
??while($r = $this->fetch_array($result))
??{
???$fields[] = $r['Field'];
??}
??$this->free_result($result);
??return $fields;
?}

参数是表的名字就ok了,会返回该表的所有字段的名字以(数组的形式返回)。?

check_fields方法

function check_fields($tablename, $array)
?{
??$fields = $this->get_fields($tablename);
??foreach($array AS $k=>$v)
??{
???if(!in_array($k,$fields))
???{
????$this->halt('MySQL Query Error', "Unknown column '$k' in field list");
????return false;
???}
??}
?}

参数第一个值就是表的名称,而第二个是字段的名称并以数组的形式传入,使用foreach拆分数据并使用in_array判断该表是否存在该字段。?

update的方法

function update($tablename, $array, $where = '')//前面对这个两个检查字段的方法介绍都是为了这个方法而准备的
?{
??$this->check_fields($tablename, $array);//check_fields
??if($where)//如果存在where的话产生不同的sql语句
??{
???$sql = '';
???foreach($array as $k=>$v)
???{
????$sql .= ", `$k`='$v'";//拆分update的数据
???}
???$sql = substr($sql, 1);//组织成一条完整而正确的sql语句(去掉前面的逗号)
???$sql = "UPDATE `$tablename` SET $sql WHERE $where";
??}
??else
??{
???$sql = "REPLACE INTO `$tablename`(`".implode('`,`', array_keys($array))."`) VALUES('".implode("','", $array)."')";
??}
??return $this->query($sql);
?}

使用方法:

$array=array('name'=>'peter','phone'=>'11234');
echo $db->update("member",$array,"`name`='test'");?

还说说这个吧escape方法

function escape($string)
?{
??if(!is_array($string)) return str_replace(array('n', 'r'), array(chr(10), chr(13)), mysql_real_escape_string(preg_replace($this->search, $this->replace, $string), $this->connid));//保证送入mysql的语句是安全的并且是能执行的(有时候你会需要它的,相信我)
??foreach($string as $key=>$val) $string[$key] = $this->escape($val);//递归使用
??return $string;
?}

正如注释说的,有时候你会需要这个方法的。?

最后说说这个halt方法吧,自身的报错方法。

function halt($message = '', $sql = '')
?{
??$this->errormsg = "MySQL Query : $sql
MySQL Error : ".$this->error()."
MySQL Errno : ".$this->errno()."
Message : $message";
??if($this->debug)//你当然可以设置关掉这个显示更详细信息的功能
??{
???$msg = (defined('IN_ADMIN') || DEBUG) ? $this->errormsg : "Bad Request. $LANG[illegal_request_return]";//额..这句代码可以kill吧,因为如果我们自己用的话就不是这样的了
???echo '<DIV style="font-size:12px;text-align:left; border:1px solid #9cc9e0; padding:1px 4px;color:#000000;font-family:Arial, Helvetica,sans-serif;">'.$msg.'</DIV>';//为了显示美观点所以加上了一大段style
???exit;
??}
?}

你可以设置是否显示更详细的错误信息的,就是这个类中的debug变量设为0就ok了。(默认是1)?

其实还有很多方法,不过paperen我觉得其他那些就没必要都放出来说说吧,相信大家都能看明白那个。

最后附上完整代码的地址http://paperen.com/demo/mysqlclass/