前言
对于一个PHP应用,可能最多的就是操作数据,以致于初学者有时只把php当做数据库增删查改的工具(这也无可厚非)。而基于框架的语言,在框架中自然不能少了对数据库操作的封装,总想打开源码,看看到底是怎么工作的,趁着在期末考试前有时间~~
thinkphp
首先是这个中国人用的最多的框架说起。
ps:我是基于thinkphp3.2来说,tp5.x党见谅~
thinkphp支持对原生的sql语句执行,如:
$db=M();
$condition="XXX";
$sql="select student.id from student where `s_name`= '$condition'";
$result=$db->query($sql);
既是使用M()方法实例一个空值,然后->query($sql),我们来看下tp的db类的源码(ThinkPHP\Library\Think\Db):
public function query($str,$fetchSql=false) {
$this->initConnect(false);
if ( !$this->_linkID ) return false;
$this->queryStr = $str;
if(!empty($this->bind)){
$that = $this;
$this->queryStr = strtr($this->queryStr,array_map(function($val) use($that)
{
return '\''.$that->escapeString($val).'\'';
}
,$this->bind));
}
if($fetchSql){
return $this->queryStr;
}
//释放前次的查询结果
if ( !empty($this->PDOStatement) ) $this->free();
$this->queryTimes++;
N('db_query',1); // 兼容代码
// 调试开始
$this->debug(true);
$this->PDOStatement = $this->_linkID->prepare($str);
if(false === $this->PDOStatement){
$this->error();
return false;
}
print_r($this->bind);//test
foreach ($this->bind as $key => $val) {
if(is_array($val)){
$this->PDOStatement->bindValue($key, $val[0], $val[1]);
}else{
$this->PDOStatement->bindValue($key, $val);
}
}
$this->bind = array();
$result = $this->PDOStatement->execute();
// 调试结束
$this->debug(false);
if ( false === $result ) {
$this->error();
return false;
} else {
return $this->getResult();
}
}
可以看到,这个function要是没有绑定参数就先是把$str参数给到一个闭包函数里进行替换,$that->escapeString($val);
public function escapeString($str) {
return addslashes($str);
}
而这个函数也只是做了个简单addslashes($str),连个mysql_real_escape_string()都没有~~~;还是有sql注入可能性,而我们要是以直接建立sql语句查询的话,是没有使用参数绑定的操作的.然后我们看到$this->PDOStatement->execute(),就是说$this->query();还是进行了pdo 的prepare和execute的操作(虽然只是对其addslashes一下),而对于不时select的sq