反射 | PDO

反射、PDO

反射

反射是指获取类、方法、属性、参数、注释等封闭信息的方法。
主要用来了解类方法、等内部的代码,反射是通过一系列的类实现的。
反射:Reflection

ReflectionClass 报告类中的信息
ReflectionFunction 报告函数的信息
RefectionException 报告异常类
RefectionMethod 报告方法中的信息

1
2
3
4
5
6
<?php
echo '<pre>';
ReflectionClass::export('Exception');

ReflectionClass::export('stdClass'); //所有类的父类
?>

通过反射获取类中的属性、方法、常量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Student{
const PI=3.14;
private $name;
public static $national='中国':
public function show(){
echo 'aa';
}
public static function test(){
echo 'bb';
}
}

//通过反射获取类的信息
//实例化反射对象
$reflection new ReflectionClass('Student');//反射Student类的信息
$consts = $reflection->getConstants();//获取所有常量
$props = $reflection->getProperties();//获取所有属性
$methods = $reflection->getMethods();//获取所有方法

自定义修改的类,方便修改

通过反射获取代理类的对象

通过调用反射类的newInstance()对象,返回反射

$reflection = new ReflectionClass('Student');
$str $reflection->newInstance(); //返回类的实例

反射可以通过反向代理来调用方法

正向代理

在运行过程中,如果感知到代理服务器存在就是正向代理。(比如:从局域网进入到外网)

反向代理

在运行过程中,不能感受到代理服务器存在。(比如京东、淘宝,服务器的请求分发我们是不知道的)

  1. 通过ReflectionMethod的invoke()反向调用
  2. 如果反向调用的是静态方法,invoke()参数为null
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <?php
    class Student{
    private $name;
    public __construct($name){
    $this->name = $name;
    }
    public function show(){
    echo $this->name,'<br>';
    }
    public static function test(){
    echo 'i am a boy!<br>';
    }
    }
    $reflection = new ReflectionClass('Student');//反射Student类的信息
    $stu = $reflection->new Instance('tom');//实例化Student对象,并传递参数
    $method = new ReflectionMethod('Student','show');//获取关于show()方法的信息
    $method->invoke($stu);//方向代理调用
    $method = new Reflection('Student','test');
    $method->invoke(NULL);
    ?>

反射是为了了解系统类或不知道内部结构的类而使用

PDO

连接MySQL的方法

方法一:mysql_*组 开启extension = php_mysql.dll扩展
mysql_connect('localhost','root','aa'); //链接
方法二:mysqli_*组开启extension = php_mysqli.dll扩展
$link = mysqli_connect('localhost','root','aa','data');

mysqli是mysql的升级版

PDO简介

PDO(PHP data object) PHP数据对象,PDO也是PHP内置的一组类(有三个),在与PDO相关的三个类中提供了一组访问数据库的轻量级,一致性的接口,无论使用什么数据库,都可以通过一致性的接口。操作数据库。
PDO是PHP5以上才支持的特性
开启相应拓展extension = php_pdo_xxx.dll

PDO的核心类:PDO、PDOStatement、PDOException

  1. PDO:表示PHP程序和数据库直接的一个连接
  2. PDOStatement:表示一条SQL处理语句,在该语句执行完成时,会返回执行结果
  3. PDOException:表示PDO产生的异常

    实例化PDO对象

    (dsn data source name) 数据源名称

    dsn 的组成结构:$dsn = 数据库类型:host=主机地址;port=端口号;dbname=数据库;charset=字符编码;
    语法:$pdo = new PDO($dsn,数据库用户名,数据库密码);
    1
    2
    3
    $dsn = 'mysql:host=127.0.0.1;port=3306;dbname=php6;charset=utf8';
    $pdo = new PDO($dsn,'root','aa');
    var_dump($pdo);

本地主机可以省略,端口号是默认值时可以省略,dbname也是可以省略的,如果dbname省略,表示连接上服务器当时没有选择数据库。
但是数据库类型(mysql:)不可以省略
数据库类型必须小写

使用PDO对象

$pdo->exec();执行数据操作语句,执行成功返回受影响的记录数,否则返回false;
$pdo->query();//数据查询语句,返回PDOStatement对象

操作数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
$dsn = "mysql:host=127.0.0.1;port=3306;dbname=php06;charset=utf8";
$pdo = new PDO($dsn,'root','aa');
$sql = "insert into admin values(2,'aa','aa',0,0)";
$rs = $pdo->exec($sql);
if($rs)
echo '插入成功<br>生成的编号是:'.$pdo->lastInsertId();
elseif($rs===0)
echo '没有数据变化';
elseif($rs===false){
echo 'SQL语句执行失败';
$error = $pdo->errorInfo();
echo '错误码:'.$pdo->errorCode(),'<br>';
echo '错误信息:'.$error[2];
}
?>

查询数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?php
$dsn = 'mysqy:host=127.0.0.1;port=3306;dbname=php06;charset=utf8';
$pdo = new PDO($dsn,'root','aa');
$sql = "select * from admin";
$stmt = $pdo->query($sql);//返回PDOStatement对象
//数据输出,array();
$rows = $stmt->fetch();
$rows = $stmt->fetch(PDO::FETCH_BOTH);//同上
$rows = $stmt->fetch(PDO::FETCH_ASSOC);//匹配成关联数组
$rows = $stmt->fetch(PDO::FETCH_NUM);//匹配成索引数组
$rows = $stmt->fetch(PDO::FETCH_OBJ);//匹配成对象
/*************************************/
$rs = $stmt->fetchALL();//匹配所有数据
$rs = $stmt->fetchALL(PDO::FETCH_ASSOC);//匹配所有数据为关联数组
/*************************************/
echo $stmt->rowCount(),'<br>';//获取总行数
echo $stmt->columnCount(),'<br>';//获取总列数
/*************************************/
//获取一条数据,匹配成类的对象
$obj = $stmt->fetchObject();
var_dump($obj);//PHP顶级父类stdClass类
class Person{}
$obj = $stmt->fetchObject('Person');
/*************************************/
$col = $stmt->fetchColumn();//匹配某一行的第0列
$col = $stmt->fetchCOlumn(1);//匹配某一行的第1列
/*************************************/
//将列绑定到变量上,绑定列的时候,列的编号是从1开始
$stmt->bindColumn(1,$id);//将第一列绑定到$id变量上
$stmt->bindColumn(2,$admin);//bindColumn('admin',$admin);将admin列绑定到$admin变量上
$stmt->fetch();
echo $id,'-',$admin;
$stmt->fetch();
echo $id,'-',$admin;
?>

以上测试,均为单行或单模块测试。其它位注释状态

脚下留心

可以通过列的索引和列的名称来绑定到变量上
绑定列和变量的时候,列的索引从1开始

取出全部数据

1
2
3
4
5
6
7
8
9
10
<?php
//通过循环获取所以数据
while($rows = $stmt->fetch(PDO::FETCH_ASSOC)){
echo $rows['id'],'-',$rows['admin'],'<br>';
}
//通过内置迭代器遍历
foreach($stmt as $rows){
echo $rows['id'],'-',$rows['admin'],'<br>';
}
?>

PDO事物处理

1
2
3
4
5
6
7
<?php
$pdo->beginTransaction();//开启事务模式
echo $pdo->exec("insert into admin values(null,'11','11',0,0)");
echo $pdo->lastInsertId();
$pdo->rollBack(); //回滚事务
$pdo->commit();//提交事务
?>

预处理语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
$sql = "insert into admin values(null,?,?,0,0)";//?是占位符
$stmt = $pdo->prepare($sql);//返回PDOStatement对象
//执行预处理语句
$stu = array(
array('aa','aa'),
array('bb','bb')
);
/**********************************/
//绑定参数并执行(方法一)
foreach($stu as $s){
$stmt->bindValue(1,$s[0]);
$stmt->bindValue(2,$s[1]);
$stmt->execute();//返回bool值
}
/**********************************/
//绑定参数并执行(方法二)
foreach($stu as $s){
$stmt->bindParam(1,$s[0]);
$stmt->bindParam(2,$s[1]);
$stmt->execute();//返回bool值

}
/**********************************/
//绑定参数并执行(方法三)
foreach($stu as $s){
$stmt->execute($s);//返回bool值
}
?>

词法分析—>语法分析->编译->执行
如果一个sql语句要被多次执行,词法分析、语法分析、编译会多次执行,这样效率低下。
使用预处理语句,对预处理语句编译后传递不同的参数即可。

bindParam 与 bindValue 的区别

bindParam第二个参数是取地址,所以只能传递变量
bindValue第二个参数可以传递值也可以传递变量

直接给预处理传递数组的时候要注意

数组中值的个数和顺序要和占位符的顺序一致

参数占位符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
$sql = "insert into admin values(null,:p1,:p2,0,0)";//参数占位符
$stmt->$pdo->prepare($sql)//预处理语句
//执行预处理语句
$stu = array(
array('aa','aa'),
array('bb','bb')8
);
foreach($stu as $s){
$stmt->bindParam(':p1',$s[0]);
$stmt->bindParam(':p2',$s[1]);
$stmt->execute();
}
?>

PDO 属性

$pdo->setAttribute(键,值);//设置PDO属性
$pdo->getAttribute(键,值);//获取PDO属性

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
$dsn = 'mysql:dbname=php6';
$pdo = new PDO($dsn,'root','aa');

echo $pdo->getAttribute(PDO::ATTR_AUTOCOMMIT);//自动提交
$pdo->setAttribute(PDO::ATTR_CASE,PDO::CASE::UPPER);//强制将列明转换为大写
$pdo->setAttribute(PDO::ATTR_ERRORMODE,PDO::ERRMODE_WARNING);//错误报告为警告模式

$stmt = $pdo->query('select * from admin');
$rows = $stmt->fetch(PDO::FETCH_ASSOC);
echo '<pre>';
var_dump($rows);
?>

PDO异常抛出

PDO 会自动抛出异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
try{
$dsn = 'mysql:dbname=php6';
$pdo = new PDO($dsn,'root','aa');//PDO会自动抛出异常
$pdo -> setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);//有错误就抛出异常
$stmt = $pdo->query('select * from admin');
var_dump($Stmt-fetch());
$age =60;
if($age>30)
throw new PDOException('年龄不能超过30');
}catch(PDOException $e){
echo '错误信息:'.$e->getmessage(),'<br>';
echo '错误行号:'.$e->getLine(),'<br>';
}
?>

单例模式实现MyPDO类的封装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
<?php
class MyPDO{
private $type;//数据库类型
private $host;//主机地址
private $port;//端口号
private $dbname;//数据库名
private $charset;//字符编码
private $user;//数据库用户名
private $pwd;//数据库密码
private $pdo;//PDO对象
private static $instance;//当前类的实例
//使用的构造函数用来阻止在类的外部实例化
private function __construct($param){
$this->initParam($param);
$this->initPDO();
}
//私有的__clone()用来阻止在类的外部克隆对象
private function __clone(){}
//公有的静态方法用来获取当前类的实例
public static function getInstance($param=array()){
if(!self::$instance instanceof self)
self::$instance = new self($param);
return self::$instance;
}
//初始化成员变量
private function initParam($param){
$this->type = isset($param['type'])?$param['type']:'mysql';
$this->host = isset($param['host'])?$param['host']:'localhost';
$this->port = isset($param['port'])?$param['port']:'3306';
$this->dbname = isset($param['dbname'])?$param['dbname']:'uiste';
$this->charset = isset($param['charset'])?$param['charset']:'utf8';
$this->user = isset($param['user'])?$param['user']:'root';
$this->pwd = isset($param['pwd'])?$param['pwd']:'123456';
}
//创建PDO对象
private function initPDO(){
$dsn = "{$this->type}:host={$this->host};port={$this->port};dbname={$this->dbname};charset={$this->charset}";
$this->pdo = new PDO($dsn,$this->user,$this->pwd);
}
//执行sql语句,返回PDOStatement对象
private function getPDOStatement($sql){
return $this->pdo->query($sql);
}
//判断匹配的类型
private function getFetchType($type){
$allow_type = array('assoc','num','both');
if(!in_array($type,$allow_type))
$type='assoc';
switch($type){
case 'assoc':
return PDO::FETCH_ASSOC;
case 'num':
return PDO::FETCH_NUM;
case 'both':
return PDO::FETCH_BOTH;
}
}
//获取所有记录,返回二位数组
public function getAll($sql,$type='assoc'){
$stmt = $this->getPDOStatement($sql);
$fetch_type = $this->getFetchType($type);
return $stmt->fetchAll($fetch_type);
}
public function getOne($sql,$type='assoc'){
$stmt = $this->getPDOStatement($sql);
$fetch_type = $this->getFetchType($type);
return $stmt->fetchAll($fetch_type);
}
public function getColumn($sql){
$stmt = $this->getPDOStatement($sql);
return $stmt->fetColumn();
}
//数据库增、删、改,返回受影响的行数
public function exec($sql){
$result = $this->pdo->exec($sql);
if(false!==$result)
return $result;
else{
$errorinfo_arr = $this->pdo->errorInfo();
echo 'SQL 语句执行失败<br>';
echo 'Error SQL:'.$sql.'<br>';
echo 'SQLSTATE error code:'.$errorinfo_arr[0].'<br>';
echo 'Driver-specific error code:'.$errorinfo_arr[1].'<br>';
echo 'Driver-specific error message:'.$errorinfo_arr[2].'<br>';
}
}
}
?>

  1. PDO的作用
    PHP数据对象,内置的一组类(有三个),在与PDO相关的三个类中提供了一组访问数据库的轻量级,一致性的接口,无论使用什么数据库,都可以通过一致性的接口,操作数据库。
  2. PDO的加载
    PDO是PHP5以上才支持的特性
    需要开启相应拓展extension = php_pdo_xxx.dll
  3. PDO技术中的PDO对象
    dsn 的组成结构:$dsn = 数据库类型:host=主机地址;port=端口号;dbname=数据库;charset=字符编码;
    语法:$pdo = new PDO($dsn,数据库用户名,数据库密码);
  4. PDO技术中的PDOStatement对象
    代表一条预处理语句,并在该语句被执行后代表一个相关的结果集。
    PDOStatement::bindColumn — 绑定一列到一个 PHP 变量
    PDOStatement::bindParam — 绑定一个参数到指定的变量名
    PDOStatement::bindValue — 把一个值绑定到一个参数
    PDOStatement::closeCursor — 关闭游标,使语句能再次被执行。
    PDOStatement::columnCount — 返回结果集中的列数
    PDOStatement::debugDumpParams — 打印一条 SQL 预处理命令
    PDOStatement::errorCode — 获取跟上一次语句句柄操作相关的 SQLSTATE
    PDOStatement::errorInfo — 获取跟上一次语句句柄操作相关的扩展错误信息
    PDOStatement::execute — 执行一条预处理语句
    PDOStatement::fetch — 从结果集中获取下一行
    PDOStatement::fetchAll — 返回一个包含结果集中所有行的数组
    PDOStatement::fetchColumn — 从结果集中的下一行返回单独的一列。
    PDOStatement::fetchObject — 获取下一行并作为一个对象返回。
    PDOStatement::getAttribute — 检索一个语句属性
    PDOStatement::getColumnMeta — 返回结果集中一列的元数据
    PDOStatement::nextRowset — 在一个多行集语句句柄中推进到下一个行集
    PDOStatement::rowCount — 返回受上一个 SQL 语句影响的行数
    PDOStatement::setAttribute — 设置一个语句属性
    PDOStatement::setFetchMode — 为语句设置默认的获取模式。
  5. PDO技术中的PDOException对象
    代表一个由 PDO 产生的错误。在自己的代码不应抛出一个 PDOException 异常
  6. PDO的操作——插入操作
    $pdo->exec(); //执行数据操作语句,执行成功返回受影响的记录数,否则返回false。
  7. 掌握PDO的操作——写操作
    ???
  8. 掌握PDO的操作——查询操作
    $pdo->query(); //数据查询语句,返回PDOStatement对象
  9. 掌握PDO的事务操作
    $pdo->beginTransaction(); //开启事务
    $pdo->rollBack(); //回滚事务
    $pdo->commit();//提交事务
  10. 掌握PDO的预处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php
$dsn='mysql:host=localhost;port=3306;dbname=php6;charset=utf8';
$pdo=new PDO($dsn,'root','aa');
//预处理语句
$sql="insert into admin values (null,?,?,0,0)"; //?是占位符
$stmt=$pdo->prepare($sql); //返回PDOStatement对象
//执行预处理语句
$stu=array(
array('aa','aa'),
array('bb','bb')
);
//绑定参数并执行(方法一)
/*
foreach($stu as $s){
$stmt->bindValue(1, $s[0]);
$stmt->bindValue(2, $s[1]);
$stmt->execute(); //返回bool值
}
*/
//绑定参数并执行(方法二)
/*
foreach($stu as $s){
$stmt->bindParam(1, $s[0]);
$stmt->bindParam(2, $s[1]);
$stmt->execute(); //返回bool值
}
*/
//绑定参数并执行(方法三),直接传递数组
foreach($stu as $s){
$stmt->execute($s); //返回bool值
}
?>
1
2
3
4
5
6
$sql="insert into admin values (null,:p1,:p2,0,0)"; //参数占位符
foreach ($stu as $s){
$stmt->bindParam(':p1', $s[0]); //绑定参数
$stmt->bindParam(':p2', $s[1]);
$stmt->execute();
}
  1. PDO的属性操作
    $pdo->getAttribute(键):获取PDO属性
    $pdo->getAttribute(键):获取PDO属性
  2. PDO的异常处理机制
    PDO会自动抛出异常,其他的地方不能自动抛出
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);设置为自动抛出异常

反射:获取类中方法、属性、参数、注释等封闭信息的方法
发射的父类(reflection)
ReflectionClass:export():反射出类的内部结构
getMethods():获取所有方法、getProterties():获取所有属性
getConstants():获取常量
通过反射类可以创建代理类的对象 newInstance()
发射通过反向代理调用对象的方法
PDO(PHP data object)提供了一组一致性的接口,用来访问不同的数据库。
要使用pdo之前必须开启pdo扩展
PDO核心类
PDO:表示PHP和数据库的链接对象
PDOStatement类,PDO执行sql语句返回的结果
PDOException:PDO异常
实例化PDO:
$dsn=’mysql:host=主机;port=端口号;dbname=数据库名;charset=字符编码’
PDO($dsn,用户名,密码)
脚下留心:数据类型要小写
使用PDO
$pdo->exec():执行数据操作语句,返回的受影响的记录数或false
$pdo->query():执行数据查询语句,返回的是PDOStatement对象
$pdo->lastInsertId():获取生成的id编号
获取PDOStatement对象中的数据
$pdo->fetch():获取一条数据
$pdo->fetchAll():获取所有数据
$pdo->fetchColumn():获取列
$pdo->fetchObject():获取一行数据,并匹配成对象
$pdo->rowCount():总行数
$pdo->columnCount():总列数
$pdo->bindColumn():将列绑定到变量上
匹配的类型:
PDO::FETCH_BOTH
PDO::FETCH_ASSOC
PDO::FETCH_NUM
PDO事务
$pdo->beginTransaction()
$pdo->rollback()
$pdo->commit()
预处理
$pdo->prepare()
位置占位符(?)
参数占位符(:参数名)
绑定参数
bindValue()
bindParam()
操作数据
$pdo->getAttribute()
$pdo->setAttribute()
异常处理
默认情况下,如果有错误就报错,不会抛出异常,设置如下语句使得自动抛出异常:$pdo->setAttribute(PDO::ERRMODE,PDO::ERRMODE_EXCEPTION)