Menu

tlanyan

十里平湖霜满天,寸寸青丝愁华年

PHP回顾之数据库操作

PHP回顾系列目录

web领域大名鼎鼎的LAMP/LNMP组合分别是Linux、Apache/Nginx、MySQL和PHP(极少情况为Perl)的首字母缩写,其中Linux是操作系统,Apache/Nginx是web服务器,MySQL是数据库,PHP是生产动态内容的编程语言。相对于同为web开发领域的Java和.Net,LAMP/LNMP的主要特定是全部都是免费且开源的。

从组合名字可以看出,MySQL是PHP的最佳数据库CP已经被广泛认可。可以毫不夸张的说,没有MySQL的PHP语言将黯然失色。MySQL是最流行的关系型数据库之一,由于其免费并且开源的特点,被许多公司修改移植并被广泛应用,也衍生了MariaDB,Percona等分支。MySQL能比较好的支持SQL语言标准,并支持大型的数据库,对PHP也有良好的支持。熟悉MySQL也是后端开发必备的基本功之一。

PHP的数据库拓展

与MySQL数据库交互的拓展有三个:mysql,mysqli和PDO_MySQL,对应三套不同风格的API。mysql拓展为连接MySQL4.1之前版本编写,不支持预编译和事务等新版特,存在注入风险。其在PHP 5.5中被奇异,并在PHP 7版本中被移除。MySQLi是MySQL的增强版本(i即improvement的缩写),提供了面向过程和面向对象两套风格的接口,支持事物等MySQL 4.1+版本的新特性。PDO是PHP数据抽象访问层(PHP Data Object)的缩写,为访问数据库定义了一个轻量级的一致接口。由于PDO不包含实现数据库的代码,必须为其制定一个具体的驱动,例如PDO_MySQL,PDO_OCI等。

三个拓展使用的数据驱动库有两个:mysqlnd和libmysqlclient。其中libmysqlclient是MySQL官方出品的驱动库,为外部程序访问和操作数据库提供了接口。mysqlnd是mysql native driver的缩写,由PHP官方出品,在5.3中被引入,在5.4+版本中作为默认的PHP MySQL拓展链接库。mysqlnd没有预先安装mysql的要求,使用了PHP内存管理可以更合理的使用内存,提高了性能。mysqlnd还支持通过插件的方式支持非MySQL数据库。官方建议优先使用mysqlnd而非libmysqlclient驱动。

数据库操作概览

日常程序开发中,常见的数据库操作包括数据定义、数据操作和事务控制,对应SQL中的DDL(Data Definition Language),DML(Data Manipulation Language)和TCL(Transaction Control Language)。create/alter/drop/truncate等对数据库的结构进行定义,属于数据定义语言DDL;select/insert/update/delete/call等对数据进行操作,属于数据操作语言DML;set transaction/rollback/commit等对事务进行控制,属于事务控制语言TCL。grant/revoke等数据库控制语言(Data Control Language, DCL)一般不会出现在程序开发中。

对应的数据接口可以分为两类:查询(query)和执行(exec)。查询要求返回结果供后续使用,执行一般不要求有结果(常见做法是返回影响的行数作为是否成功的标识)。

从组织结构看,数据库操作有三个要素:数据库连接、执行语句和结果集。

下文以PDO为例,示例数据库操作。

PDO操作

以上代码包含了常见的数据库连接、数据增删查改、表结构操作和事物控制。数据库连接对象,命令语句和结果集,是数据操作的三个重要因素。

SQL注入

SQL注入是web开发中绕不过去的安全议题。发生SQL注入的本质原因是执行了动态的命令,如果执行的命令都是限定的,就会会出现SQL注入的现象。要防范SQL,关键点是使用编译好的命令(存储过程)或者预编译命令。

存储过程在数据库中定义,程序中按照指定参数call即可调用。对于动态语句的,PDO提供了预编译功能(如果数据库不支持预编译,PDO可以模拟预编译,需要设置PDO::ATTR_EMULATE_PREPARES为true)。预编译命令后,返回一个PDOStatement对象,绑定参数后即可安全的执行命令。

以下代码是PDO预编译的一个例子:

杂项

  • 设置出错模式为PDO::ERRMODE_EXCEPTION后,执行语句过程中出现错误,将抛出PDOException的实例对象
  • PDOStatement的bindParam和bindValue,类似于函数中的引用调用和传值调用:bindParam将变量绑定,变量的值改变,则执行命令中参数也改变。bindValue则是绑定值,变量改变不影响执行的语句。
  • 事务支持依赖于数据表使用的引擎。MySQL的MyISAM引擎不支持事务,InnoDB引擎支持(InnoDB为5.5+后的默认引擎)。可通过show engines命令查看数据库支持的引擎已经对事务的支持情况。

发表评论

Scroll Up