Thinkphp基础 – 数据库连贯操作

Thinkphp提供数据库连贯操作的组件,方便在进行增删改查时更清晰流畅。

查询条件 WHERE

通过 where() 方法可以对sql语句添加where条件

public function index(){
	$user = M("user");
	if(IS_GET){
		/*这段是不使用where方法的
		$username = I("username");
		$where = "username = '$username'";
		$data = $user->where($where)->select();
		*/
		$map = I();
		$map = array_filter($map);	//过滤值为空的数组
		$map['username'] = array('LIKE',"%{$map['username']}%");	//模糊匹配
		$data = $user->where($map)->select();
	}else{
		$data = $user->select();
	}
	$this->assign("users",$data);
	$this->display();
}

查询字段 field

通过 field() 方法可以对select查找的字段进行限制,同时也能对增加和修改数据时限制字段。

public function index(){
		$user = M("user");
		if(IS_GET){
			$map = I();
			$map = array_filter($map);	//过滤值为空的数组
			$map['username'] = array('LIKE',"%{$map['username']}%");	//模糊匹配
			$data = $user->where($map)->field("id,username,password,email")->select();
			//$data = $user->where($map)->field("id",true)->select();  //field方法设置true可以选择除了 id 以外的其他字段
		}
		$this->assign("users",$data);
		$this->display();
	}

排序 order

通过 order() 方法可以对查询结果进行排序

public function index(){
	$user = M("user");
	if(IS_GET){
		$map = I();
		$map = array_filter($map);	//过滤值为空的数组
		$map['username'] = array('LIKE',"%{$map['username']}%");	//模糊匹配
		$data = $user->where($map)->order("id DESC")->field("id,username,password,email")->select();
	}
	$this->assign("users",$data);
	$this->display();
}

多表查询 table

多表查询,可以使用 table() 方法

public function index(){
	$model = M();
	$data = $model->field("article.*,user.username")->table("tp_user user,cms_article article")->where("user.id=article.userId")->select();
	dump($data);
}

注意:使用 table 多表查询时表名要带上前缀,同时where条件至少有表的个数减一个

表关联 join

使用join()可以对两张表进行关联,LEFT JOIN 或 RIGHT JOIN

public function index(){
	$article = M("article");
	//$data = $article->join("tp_user ON tp_user.id = tp_article.userId")->field("tp_article.*,tp_user.username")->select();
	$data = $article->join("LEFT JOIN tp_user ON tp_user.id = tp_article.userId")->field("tp_article.*,tp_user.username")->select();
	dump($data);
}

 

Thinkphp基础 – 数据的增删改查

任何时候对数据的增删改查都是最基础的操作,Thinkphp 为我们提供了一套对数据操作的方法。下面分别介绍下:

连接数据表,并查找数据

连接数据表很简单 $user = M(“user”);  使用 M 方法连接表格,里面的表名称不要带前缀(因为前缀已经在配置文件中设置了)。

查找 $user->select(); 使用 select() 就可以查找到内容了,这里是查找到表内全部的数据

$user = M("user");
$data = $user->select();
//这样就获取到user表内的全部数据

插入数据

插入数据  $user->add($data);  这里的 add() 方法可以插入数据,传入的参数是数组。

if(IS_POST){
  $data = $_POST;
  $user = M("user");
  $user->add($data);  //插入数据
}

删除数据

删除数据 $user->delete($id);  使用 delete() 方法可以删除数据。

public function del($id){
	$user = M("user");
	$res = $user->delete($id);
	if($res){
		$this->success("删除成功!");
	}else{
		$this->error("删除失败!");
	}
}

修改数据

修改数据 $user->save($data); 使用 save() 方法修改数据。

创建数据对象

创建数据对象的目的是过滤掉提交的数据中有数据表中不存在的数据。对于提交数据库更安全方便。

创建数据对象  $user->create();

以下是完整的代码

<?php 
namespace Admin\Controller;
use Think\Controller;

class UserController extends Controller{
	public function index(){
		$user = M("user");
		$data = $user->select();
		$this->assign("users",$data);
		$this->display();
	}
	public function add(){
		if(IS_POST){
			$user = M("user");
			$data = $_POST;
			$data['password'] = md5($data['password']);
			if($user->create($data)){	//如果create方法不传参,默认是获取$_POST数据
				if($user->add()){	//add不需要传参,直接从create里获取数据
					$this->success('添加成功!',U('Admin/User/index'));
				}else{
					$this->error('添加失败!');
				}
			}else{
				$this->error("添加失败!");
			}		
			exit;
		}
		$this->display();
	}
	public function del($id){
		$user = M("user");
		$res = $user->delete($id);
		if($res){
			$this->success("删除成功!");
		}else{
			$this->error("删除失败!");
		}
	}
	public function mod($id = 0){
		$user = M("user");
		if(IS_POST){
			$data = I();
			if($data['password']){
				$data['password'] = md5($data['password']);
			}else{
				unset($data['password']);
			}
			if($user->create($data)){
				if($user->save()){
					$this->success("修改成功!",U("Admin/User/index"));
				}else{
					$this->error("修改失败!");
				}
			}else{
				$this->error("修改失败!");
			}		
			exit;
		}
		$data = $user->find($id);		
		$this->assign("user",$data);
		$this->display();
	}
}

这里要注意:

查询的数据绑定用 $this->assign(“users”,$data);

当前方法绑定到模板哟你 $this->display();

PHP面向对象 – 使用PDO连接数据库

PDO(php data object)扩展类库为php访问数据库定义了轻量级的、一致性的接口,它提供了一个数据库访问抽象层,这样,无论你使用什么数据库,都可以通过一致的函数执行查询和获取数据,大大简化了数据库的操作,并能够屏蔽不同数据库之间的差异,使用pdo可以很方便地进行跨数据库程序的开发,以及不同数据库间的移植,是将来php在数据库处理方面的主要发展方向,它可以支持mysql,postgresql,oracle,mssql等多种数据库。

PDO安装

1.编辑php.ini文件:

extension=php_pdo.dll

extension=php_pdo_mysql.dll

2.重启apache服务

3.打开phpinfo.php查看是否有pdo

创建PDO对象与连接使用PDO对象

1.创建PDO对象

$dsn = ‘mysql:dbname=testdb;host=127.0.0.1’; //连接MySQL数据库的DSN

$user = ‘dbuser’; //MySQL数据库的用户名

$password = ‘dbpass’; //MySQL数据库的密码

try {

$dbh = new PDO($dsn, $user, $password);

} catch (PDOException $e) {

echo ‘数据库连接失败: ‘ . $e->getMessage();

}

2.设置连接字符集

设置php连接mysql时的客户端字符串和连接字符串集为:

$pdo->exec(“set names utf8”);

或者:

$pdo->query(“set names utf8”);

3.调整PDO行为

setAttribute() //设置PDO行为属性

getAttribute() //得到PDO行为属性值

4.设置错误处理模式

PDO::ATTR_ERRMODE //错误处理模式

PDO::ERRMODE_SILENT:不报错误(忽略)(0)

PDO::ERRMODE_WARNING:以警告的方式报错(1)

PDO::ERRMODE_EXCEPTION:以异常的方式报错(推荐使用)(2)

设置方式:

在构造时初始化错误模式通过pdo对象的setAttribute()方法设置。

$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);

面向过程

$con->errorCode():SQL语句错误代码

$con->errorInfo():错误信息

面向对象

捕获PDOException异常对象

5.使用PDO执行SQL语句

exec()方法用于执行有影响行数的语句

query()方法用于执行有结果集的语句

下面是栗子:

//连接数据库
$dsn = 'mysql:dbname=xiaofan;host=localhost';
$username = 'root';
$password = '';
try{
	$dbh = new PDO($dsn,$username,$password);
}catch(PDOException $e){
	echo $e->getMessage();
}
$dbh->exec("set names utf8");	//设置php连接mysql时的客户端字符串和连接字符串集

$sql = "insert into users(username,tel) values('xiaoming','123456789')";
$dbh->exec($sql);	//执行插入 删除等影响行数的语句,使用exec()

$sql = "select username,tel from users";
$query = $dbh->query($sql);	//执行查询语句 有结果集的语句,使用query()
$result = $query->fetchAll();	//通过一次调用返回所有结果,结果是以数组形式保存
var_dump($result);

以上是简单的PDO执行方法,而实际中我们会使用下面的PDO预处理方法执行SQL语句。

PDO预处理

PDO预处理相比上面的简单方法最大优势是:防止SQL注入漏洞,有利于网站数据的安全。同时,也有利于多次执行。

1.PDOStatement对象的方法

fetch()  返回结果集的下一行,结果指针下移,到头返回false

fetchAll()  通过一次调用返回所有结果,结果是以数组形式保存

execute()    负责执行一个准备好了的预处理语句

rowCount()    返回使用增、删、改、查操作语句后受影响的行总

bindParam()  将参数绑定到相应的查询占位符上

bindColumn()  将查询结果的字段绑定变量

参数: PDO::FETCH_BOTH (default)、PDO::FETCH_ASSOC、 PDO::FETCH_NUM、PDO::FETCH_OBJ、 PDO::FETCH_COLUMN表示取指定某一列如:$rslist = $stmt->fetchAll(PDO::FETCH_COLUMN,2);取第三列数据

2.准备语句

得到pdo预处理对象的方法:

$sql=“select * from user order by id”;

$sth=$pdo->prepare($sql);

以上代码中的$sth即为预处理对象

在PDO中参数式的SQL语句有两种(预处理sql):

insert into stu(id,name) value(?,?); //?号式(适合参数少的)

insert into stu(id,name) value(:id,:name);//别名式(适合参数多的)

3.绑定参数

A.点位符方式

$stmt->bindParam(1, $name, PDO::PARAM_STR);

B.别名方式

$stmt->bindParam(‘:name’, $name);

这里特别注意:不能传入字符串,必须用变量 $stmt->bindParam(‘:name’,’xiaofan’);这样是错误的

4.执行预处理方式

A.占位符?

$query = “INSERT INTO contactInfo (name, address, phone) VALUES (?, ?, ?)”; $stmt = $dbh->prepare($query);

//传递一个数组为预处理查询中的问号参数绑定值,并执行一次。

$stmt->execute(array(“赵某某”, “海淀区”, “15801688348”));

//再次传递一个数组为预处理查询中的问号参数绑定值,并执行第二次插入数据。 $stmt->execute(array(“孙某某”, “宣武区”, “15801688698”));

B.占位符 :

$query = “INSERT INTO contactInfo (name, address,) VALUES (:name, :address)”;

//调用PDO对象中的prepare()方法准备查询,使用命名参数

$stmt = $dbh->prepare($query);

//传递一个数组为预处理查询中的命名参数绑定值,并执行一次。

$stmt->execute(array(“name”=>”赵某某”,”address”=>”海淀区”));

//再次传递一个数组为预处理查询中的命名参数绑定值,并执行第二次插入数据。

$stmt->execute(array(“name”=>”孙某某”,”address”=>”宣武区”));

5.预处理查询

$query = “SELECT uid, name, phone, email FROM contactInfo WHERE

$stmt = $dbh->prepare($query);   //准备声明好的一个查询

$stmt->execute();          //执行准备好的查询

$stmt->bindColumn(1, $uid);     //通过列位置偏移数绑定变量

$stmt->bindColumn(2, $name);   //通过列位置偏移数绑定变量$name

$stmt->bindColumn(‘phone’, $phone); //绑定列名称到变量$phone上

$stmt->bindColumn(’email’, $email); //绑定列名称到变量$email上

while ($stmt->fetch(PDO::FETCH_BOTH)) {

echo $uid.”\t”.$name.”\t”.$phone.”\t”.$email.”\n”;

}

下面是栗子:

//连接数据库
$dsn = 'mysql:dbname=xiaofan;host=localhost';
$username = 'root';
$password = '';
try{
	$dbh = new PDO($dsn,$username,$password);
}catch(PDOException $e){
	echo $e->getMessage();
}
$dbh->exec("set names utf8");	//设置php连接mysql时的客户端字符串和连接字符串集
//PDO预处理执行
//使用?占位符
$sql = "insert into users(username,tel) values(?,?)";
$stmt = $dbh->prepare($sql);
$arr = array('user1',11111111);
$stmt->execute($arr);

//使用:占位符
$sql = "insert into users(username,tel) values(:username,:tel)";
$stmt = $dbh->prepare($sql);
$arr = array("username"=>"user3","tel"=>"333333333");
$stmt->execute($arr);

//PDO预处理查询
$sql = "select username,tel from users where id > :id";
$stmt = $dbh->prepare($sql);
$stmt->execute(array("id"=>2));
$stmt->bindColumn(1,$username); //通过列位置偏移数绑定变量
$stmt->bindColumn('tel',$tel);	//绑定列名称到变量上
//用while循环获取每行内容
while($stmt->fetch(PDO::FETCH_ASSOC)){
	echo $username.'--'.$tel.'<br>';
}
//也可以直接将结果放入一个数组
$result = $stmt->fetchAll(PDO::FETCH_COLUMN,1);	//获取第二列数据,注意是列不是行
var_dump($result);
//不使用bindColumn绑定方法
while($result = $stmt->fetch(PDO::FETCH_BOTH)){
	echo $result['username'].'--'.$result['tel'].'<br>';
}

PDO事务处理

1.MySQL的事务处理

事务:将多条sql操作(增删改)作为一个操作单元,要么都成功,要么都失败。

MySQL对事务的支持:

被操作的表必须是innoDB类型的表(支持事务)

MySQL常用的表类型:MyISAM(非事务)增删改速度快、InnodB(事务型)安全性高

2.构建事务处理应用程序

开启一次事务:

$pdo->beginTransaction();

提交一次事务:

$pdo->commit();

回滚一次事务:

$pdo->rollback();

注意如下设置:

$pdo->setAttribute(PDO::ATTR_AUTOCOMMIT,0);

$pdo->setAttribute(PDO::ATTR_AUTOCOMMIT,1);

以下是事务提交的栗子

$db->beginTransaction();
try{
$sql = 'INSERT INTO user(username,tel) values(:username,:password)';
$smt = $db->prepare($sql);
$arr = array("username" => "mazi","password" => "963");
if (!$smt->execute($arr)){
	throw new PDOException('first error');
}
$sql = 'INSERT INTO admin(username,tel) values(:username,:password)';
$smt = $db->prepare($sql);
$arr = array("username" => "andy","password" => "951");
if (!$smt->execute($arr)){
	throw new PDOException('second error');
}
$db->commit();
}catch(PDOException $e){
	$db->rollback();
	echo $e->getMessage(). '<br>';	
}

 

PHP入门 – MySQL数据库/数据表设计

动态网站都是对数据进行操作,所谓的动态网站就是基于数据库开发的系统,最重要的就是数据管理,或者说我们在开发时都是在围绕数据库在写程序。

在我们使用PHP开发中小型网站时,一般首选使用MySQL数据库。LAMP或LNMP都是开源免费的,是我们经常搭建的服务器环境。

MySQL数据库常用操作

mysql –h 服务器主机地址 –u 用户名 –p 用户密码

只有客户机所在的主机被授予权限才能去连接MySQL服务器。

注意:

每个SQL命令都需要使用分号来完成

可以将一行命令拆成多行

可以通过\c来取消本行命令

可以通过\q、exit、ctrl+c或者quit来退出当前客户端

MySQL数据库创建/删除/选择

创建数据库

CREATE DATABASE [IF NOT EXISTS] 数据库名称;

删除数据库:

DROP DATABASE [IF EXISTS] 数据库名称;

显示当前数据库服务器下的所有数据库列表:

SHOW DATABASES;

选择数据库:

USE 数据库名称;

注意:

MySQL数据库中命令不区分大小写。

每创建一个数据库,就会在data目录下创建一个以此数据库名称命名的文件夹。

在Windows下,数据库名称也是不区分大小写的,但在Linux下,数据库名称严格区分大小写。

数据表的设计

1.数据列四大数据类型

数值类数据列类型 字符串类数据列类型 日期和时间类数据列类型 NULL值

1.1数值类数据列类型

图片1 图片2

整型注意事项:

INT(3)、SMALLINT(3)等整型后面的数字不会影响数值的存储范围,只会影响显示,整型后面的数字只有配合零填充的时候才有实际意义。整型后面的数字可以省略

浮点型注意事项:

浮点型后面的数字会将存入的数字四舍五入,例如:把一个1.234存入FLOAT(6,1)数据列中,结果是1.2,6代表显示长度,1代表小数位长度,会四舍五入.

1.2字符串数据列类型

图片3

字符串类型注意事项:

(1)CHAR和VARCHAR类型

CHAR和VARCHAR类型的长度范围都在0~255之间

在使用CHAR和VARCHAR类型时,当我们传入的实际的值的长度大于指定的长度,字符串会被截取至指定长度

在使用CHAR类型时,如果我们传入的值的长度小于指定长度,实际长度会使用空格补至指定长度

在使用VARCHAR类型时,如果我们传入的值的长度小于指定长度,实际长度即为传入字符串的长度,不会使用空格填补

CHAR要比VARCHAR效率更高,但占用空间较大

(2)BLOB和TEXT类型

BLOB和TEXT类型是可以存放任意大数据的数据类型

BLOB区分大小写,TEXT不区分大小写

(3)ENUM和SET类型

ENUM和SET类型是特殊的的串类型,其列值必须从固定的串集中选择

ENUM只能选择其中一个值,SET可以选择多个值

1.3时间和日期类据列类型

图片4

日期类型注意事项: 存储日期时,我们可以使用整型来进行存储时间戳,这样做便于我们进行日期的计算

1.4 NULL值

NULL值注意事项:NULL意味着“没有值”或“未知值,可以测试某个值是否为NULL,不能对NULL值进行算术计算,对NULL值进行算术运算,其结果还是NULL,0或NULL都意味着假,其余值都意味着真。

2.数据字段属性

UNSIGNED 只能用于设置数值类型,不允许出现负数,最大存储长度会增加一倍

ZEROFILL 只能用于设置数值类型,在数值之前会自动用0补齐不足的位数

AUTO_INCREMENT 用于设置字段的自动增长属性,每增加一条记录,该字段的值会自动加1

NULL和NOT NULL 默认为NULL,即插入值时没有在此字段插入值,默认为NULL值,如果指定了NOT NULL,则必须在插入值时在此字段填入值

DEFAULT 可以通过此属性来指定一个默认值,如果没有在此列添加值,那么默认添加此值

3.索引

索引主要包含 主键索引(PRIMARY KEY)、唯一索引(UNIQUE)、常规索引(INDEX)、全文索引(FULLTEXT)。

3.1 主键索引

主键索引是关系数据库中最常见的索引类型,主要作用是确定数据表里一条特定的数据记录的位置。我们可以在字段后添加PRIMARY KEY来对字段设置为主键索引。

注意:

最好为每张表指定一个主键,但不是必须指定。

一个表只能指定一个主键,而且主键的值不能为空

主键可以有多个候选索引(例如NOT NULL,AUTO_INCREMENT)

3.2 唯一索引

唯一索引与主键索引一样,都可以防止创建重复的值。但是,不同之处在于,每个数据表中只能有一个主键索引,但可以有多个唯一索引。我们使用关键字UNIQUE对字段定义为唯一索引

3.3 常规索引

常规索引技术是关系数据查询中最重要的技术,如果要提升数据库的性能,索引优化是首先应该考虑的,因为它能使我们的数据库得到最大性能方面的提升。常规索引也存在缺点:

多占用磁盘空间

会减慢插入,删除和修改操作

需要按照索引列上排序格式执行

创建索引我们可以使用INDEX和KEY关键字随表一同创建。

4.数据表操作

4.1 创建表

创建数据表之前,我们应该注意:创建数据库(如已存在则不需要创建),选择数据库,在该数据库当中创建数据表

创建数据表需要注意:指定数据表的名称(数据表不能重名),指定该表的字段名称、字段数据类型、字段索引,指定表类型和表默认字符集(可省略)

图片1

图片2

注意事项:

表的字段之间要使用逗号隔开。

建表的最后一句一定不能有逗号。

表名称和字段名称尽量不要使用MySQL系统的关键字

如果一定要使用关键字,我们可以使用反引号将表名称和字段名称包含起来来进行过滤屏蔽。

使用反引号会使建表效率增高。

数据表名称和字段名称不能重名

AUTO_INCREMENT属性必须依附于主键索引或唯一索引

查看表结构命令: DESC 表名;

4.2 修改表

修改表的语法:ALTER TABLE 表名 ACTION;

我们可以对表进行修改字段,添加字段,删除字段,添加索引,删除索引,更改表名称,更改字段名称,更改auto_increment属性的初始值等。

4.2.1 修改字段

我们使用change或者是modify关键字

ALTER TABLE `users` CHANGE `username` `uname` VARCHAR(32) NOT NULL;

ALTER TABLE `users` MODIFY `username` VARCHAR(32) NOT NULL;

由上例可以发现:

change可以改变字段名称,而modify不可以

4.2.2 添加字段

我们使用add关键字

ALTER TABLE `uses` ADD `tname` VARCHAR(32) NOT NULL;

这样我们就会新增一个tname字段。

如果添加在某个字段后面添加一个字段,可以按照下面的方法写:

ALTER TABLE `users` ADD `email` VARCHAR(20) NOT NULL DEFAULT ”  AFTER `tel`;

这样添加的 email 字段就会紧挨这字段 tel 后面

4.2.3 删除字段

我们使用drop关键字

ALTER TABLE `users` DROP `tname`; 这样我们会删除tname字段

4.2.4 更改表名称:

我们使用rename关键字

ALTER TABLE 旧表名 RENAME AS 新表名; 将旧表名更改为新表名

更改AUTO_INCREMENT初始值:

ALTER TABLE 表名称 AUTO_INCREMENT=1;  将AUTO_INCREMENT的初始值设置为1

4.2.5 添加索引:

我们使用add关键字

ALTER TABLE `uses` ADD INDEX/UNIQUE/PRIMARY KEY/索引名 (字段名称)

这样会在该字段上建立索引(普通索引,唯一索引,主键索引)。

ALTER TABLE user ADD UNIQUE username_unqiue (username);
ALTER TABLE user ADD INDEX username_index (username);

注意:在创建唯一索引时,有时会出现提示 ERROR 1062 (23000): Duplicate entry ‘***’ for key ‘username_unique’

这个问题的原因是该字段中已经存在重复的值,所以不能直接创建唯一索引。解决办法是删除重复的值,或清空表数据。

查看表里的全部索引

SHOW INDEX FROM 表名称;

或者 SHOW KEYS FROM 表名称;

查询的结果分别是:

· Table
表的名称。
· Non_unique
如果索引不能包括重复词,则为0。如果可以,则为1。
· Key_name
索引的名称。
· Seq_in_index
索引中的列序列号,从1开始。
· Column_name
列名称。
· Collation
列以什么方式存储在索引中。在MySQL中,有值‘A’(升序)或NULL(无分类)。
· Cardinality
索引中唯一值的数目的估计值。通过运行ANALYZE TABLE或myisamchk -a可以更新。基数根据被存储为整数的统计数据来计数,所以即使对于小型表,该值也没有必要是精确的。基数越大,当进行联合时,MySQL使用该索引的机 会就越大。
· Sub_part
如果列只是被部分地编入索引,则为被编入索引的字符的数目。如果整列被编入索引,则为NULL。
· Packed
指示关键字如何被压缩。如果没有被压缩,则为NULL。
· Null
如果列含有NULL,则含有YES。如果没有,则该列含有NO。
· Index_type
用过的索引方法(BTREE, FULLTEXT, HASH, RTREE)。
· Comment

4.2.6 删除索引:

删除索引研究了半天,终于知道怎么删除了。

(1)删除UNIQUE唯一索引和INDEX常规索引的方法:

ALTER TABLE `users` DROP INDEX 索引名称;

注意:INDEX可以删除唯一索引

(2)删除PRIMARY KEY 主键索引,去掉一个表格的主键需要分2中情况:

A、该列(column)不光设置为主键(primary key),还有自增长(auto_increment);

句式:alter table +表名+ modify id int, drop primary key;

B、如果没有设置为自增长(auto_increment),那么可以直接删除主键(primary key );

句式:alter table +表名+drop primary key;

这样我们会删除这个索引,我们可以使用show indexes from 表名查看当前表索引。

4.3 删除表

DROP TABLE [IF EXISTS] 表名称;