在Laravel中,对数据库的访问可以通过查询构造器或Eloquent ORM实现,不同的方法实现不同的底层封装,这两种封装都有同一个目的,即对底层不同数据库提供统一的操作接口.默认情况下,Laravel支持四种数据库系统,即MySQL、Postgres、SQLite和SQL Server.也就是说,当服务器程序数据库改变时(如从SQLite迁移到MySQL上),如果对数据库的操作是通过查询构造器或Eloquent ORM实现的,那么只需要修改数据库配置文件的相关配置,对于程序不需要进行任何修改就可以实现,这样将会极大提高Laravel框架的扩展性.查询构造器的底层其实用到的还是PHP数据库抽象层的PDO扩展,该扩展是一个“轻量级”的数据库扩展,数据库的操作需要自己设计SQL语句来执行,而Laravel框架的查询构造器是在PDO扩展基础上设计的一个“重量级”的数据库扩展,它将SQL语句的设计都进行了封装,将需要变化的部分进行了分离并以配置文件的方式进行设置,对数据库常用的操作进行了封装,提供了统一的接口,更加方便使用.下面将通过PHP中数据库的操作、数据库连接的封装、查询构造器的实现、查询构造器的使用和查询构造器的数据库操作五个部分进行介绍,介绍过程将以MySQL数据库为例.
一般关系型数据库采用的是“客户机/服务器”的体系结构,客户端通过SQL语句操作服务端.在PHP中,有两大类操作数据库的扩展,一种是针对各数据库开发的专用扩展,如MySQL扩展、SQLite3扩展;另一种是数据库抽象层,如PDO(PHP Data Objects,PHP数据对象)、ODBC(Open Database Connectivity,开放数据库互连).在PHP开发中,以前的开发中大多使用专用扩展,因为PDO是在PHP5.1版本才引入的,而目前开发中大多使用PDO扩展.Laravel框架中关于数据库操作的底层使用的就是PDO扩展.
那么这两种扩展有什么区别呢?一是开发思想不同,针对各数据库开发的专用扩展采用的是面向过程的思想开发的,而PDO扩展采用的是面向对象的思想开发的.二是提供的接口针对的数据库范围不同,专用扩展只是针对某一种数据库开发的,如MySQL扩展提供的接口只能操作MySQL数据库,当更改底层数据库时,就要重新安装相应数据库的扩展,也需要对数据库的操作代码重新编程;而数据库抽象层则针对多种数据库提供统一的接口,采用这种接口编写的程序,在更改底层数据库时,不需要重新安装数据库抽象层,但需要安装对应的数据库驱动,代码部分只需要修改少许的连接和设置等操作,其他对数据的操作不需要修改,扩展性好,其作用方式如图所示.三是平安性,在关系型数据库中,使用专用扩展需要解决SQL注入的问题,而使用PDO扩展可以避免这个问题.
下面针对MySQL数据库介绍专用扩展和PDO扩展的用法,一是使读者了解两者的区别和效果,二是有助于读者了解Laravel框架关于数据库操作底层的实现.1.MySQL扩展应用;前面提到,专用MySQL扩展是采用面向过程的思想开发的,当PHP安装了MySQL扩展后,就可以直接使用相应的函数来执行SQL语句,从而完成对数据库的操作,这里用到的是mysql_query()函数执行SQL语句.一般将SQL语句分为两类:一类是执行SQL语句后有返回结果的,如select语句、desc语句等;第二类是没有返回结果的,如delete语句、insert语句等.对于没有返回结果的语句不需要设置返回值,可以通过mysql_insert_id()函数获取最后操作数据的行数及通过mysql_affected_rows()获取操作影响的行数.对于有返回结果的语句需要设置返回值,可以通过mysql_fetch_assoc()函数实现返回值的获取.下面给出一个简单的对数据库进行操作的源码:
通过上述源码可以看出,操作一个数据库需要四个步骤:一是连接数据库的服务端;二是选择数据库;三是准备SQL语句并执行;四是关闭数据库.这些步骤所用到的函数都是对应数据库专用的扩展函数,在扩展方面无法迁移到其他数据库,在平安性方面,因为是一次性完成SQL语句命令和数据的设定及编译(一般数据库将SQL语句从客户端发送到服务端时需要先编译才能执行),所以容易受到SQL注入的攻击.
2.PDO扩展应用;目前,在PHP程序设计中对数据库的操作广泛采用PDO扩展方式,因为该扩展对不同数据库提供统一的接口,只需要添加相应数据库的驱动就可以实现数据库的迁移,扩展性更好.同时,PDO将服务器端命令语句的编译和数据添加的分离思想应用到客户端,可以避免SQL注入的攻击,平安性更好.下面给出基于PDO扩展来操作MySQL数据库的源码:
通过上述源码可以看出,采用PDO扩展对数据库操作的步骤与采用专用MySQL扩展对数据库操作的步骤几乎相同,但在实现方式上却不同.一是在PDO扩展中对MySQL数据库的操作方法中几乎没有与该数据库关联的部分,只有在建立连接时构造DSN(Data Source Name,数据源名称)时以“mysql:host=localhost;dbname=Laravel”的方式声明了数据库类型,而具体对数据库的操作方法与数据库类型无关,所以在数据库迁移时,只需要修改这个连接参数就可以实现,扩展性更好;二是在执行数据库操作时,可以先通过PDO类的prepare()方法将操作命令发送到服务端编译,再通过PDOStatement类的execute()方法将数据发送到服务端并执行,这种方法既可以提高多次执行同一条操作命令时的速度,也可以避免SQL注入的危险,所以效率、平安性都更高.