大多数应用通常都会与可以有序存放数据的容器一同工作。举个直接的例子——文件,没有什么比它更符合我们的目的,但往往我们会使用效率更高的数据库引擎。PHP对大多数使用SQL(结构化查询语句)查询的关系型数据库提供了良好的支持。想要利用好数据库,很重要的一点是需要具备扎实的SQL基础,还有如何通过PHP连接数据库。本章将介绍基本的SQL与如何通过PHP Data Objects(PDO)连接数据库。
Siemen言:好几天没翻了,因为家务繁重加上最近学习JAVA的压力也比较大,尽量每天可以出一个小节。
献上目录:
PHP的面向对象技术是从PHP4中成长而来的。PHP5中的新的OOP模型使得健壮且可扩展的程序成为可能,同时对于易用性、封装与重用代码打下基础。而且,OOP并不仅仅只是一种编程的思想,你可以切实的在开发中实施,它是开发者手中珍贵的工具,合理的利用它,可以提升代码质量。
通过PHP的Reflection API的函数与对象,可以调查脚本代码,比如运行时检查函数和对象。
反射可以的通途很多;例如,它可以用来生成简单的文档,或者确认脚本中是否存在某个函数等。举例来说:
PHP 5之前的版本,如果实例化一个不存在的类的对象,或者调用一个不存在的类的内不的静态方法将会导致一个致命错误。这意味着需要事先引入所有可能被使用的类文件,更好的办法是在被需要时才引入文件——为了不漏掉文件,就需要一个复杂的文件引入机制来处理外部文件的引入。
为了解决这个问题,PHP5中的“autoload”特性,可以实现“自动载入”,也就是按需载入文件。当试图对一个不存在的类进行类型暗示、静态调用,或者试图实例化一个对象,PHP就会使用调用__autoload()这个全局函数试图载入这个类文件。如果在调用autoload()后,类还是没有定义,解释器会停止工作并且抛出一个致命错误。
function __autoload($class)
{
// 需要 PEAR-compatible 类库的支持
require_once str_replace("_", "/", $class);
}
$obj = new Some_Class();
当对Some_Class类进行实例化,__autoload()就会被调用,传入"Some_Class.php"作为参数$class的值。函数中会把下划线替换成斜杠并通过require_once()引入。
通过使用__autoload()对于单命名空间来说非常有帮助;它会按需载入类文件,因此,用不到的类文件就不会被载入。但是当你在编写复杂的代码和使用不同的的类库时(比如:PEAR和一些大型应用)调用__autoload()会变得很难操控,从而使程序变得庞大而缓慢。
Siemen注:说实话这块真的不是看的很明白。
幸好标准的PHP类库(SPL)提供了一个简单的解决办法,将autoloader堆砌在其自身的顶部。如果一个执行失败了,下一个autoloader会接着尝试载入,直到文件被载入或者产生一个致命错误。
默认的,SPL使用自己的autoloader,称为spl_autoload();这是内建函数,检查所有的引入路径的文件名是否与需要载入的类的名称小写符合,且扩展名是.inc, .php或者其他在spl_autoload_extenstions()中用都好隔开传入的扩展名列表。
另外,按需载入可以通过spl_autoload_register()来加入堆栈。第一次调用这个函数用来替换__autoload()——也就是说,如果已经存在一个用户自定义__autoload()就需要将其按顺序注册到SPL中以便继续运行:
sql_autoload_register('spl_autoload');
if (function_existed('__autoload')) {
spl_autoload_register('__autoload');
}尽管面向对象技术经过了多年的洗礼和成长,而异常这个机制却是最近才加入到PHP中的。异常提供了一个错误控制机制,它相对与传统的PHP的错误句柄来说提供了更高等级的控制。
以下例举了一些与“常规”PHP错误与异常的不同:
另一种在PHP 5中加入的信特性就是接口与抽象类。它们的作用是用来创建强制性基于一些设计的类。一个抽象类本质上来说就是定义一个特殊类型整体的骨架——举例来说,可以使用一个抽象类定义一个基本的“车”的概念,拥有两扇车门,一个锁和可以解锁与闭锁的方法。抽象类不能实例化,但是可以被继承,因此继承下来的抽象方法将在子类中进行具体化。例如:
abstract class DataStore_Adapter
{
private $id;
abstract function insert();
abstract function update();
public function save()
{
if (!is_null($this->id)) {
$this->update();
} else {
$this->insert();
}
}
}
class PDO_DataStore_Adapter extends DataStore_Adapter
{
public __construct($dsn) {
//...
}
public insert() {
//...
}
public update() {
//...
}
}
作者提示:类中只要出现抽象方法,则此类必须要声明为abstruct。
如上代码所示,定义了一个Data_Adapter的类,同时定义了两个抽象方法insert()和update()。需要提醒的是,这两个方法都没有身体(Siemen注:也就是没有实现)——这是抽象类的必备条件之一—也就是为什么类本身会被修饰成abstract,其原因就是需要满足解释器语法需要。用PDO_DataStore_Adapter类继承DataStore_Adapter,而其PDO_DataStore_Adapter类实现了insert()与update()也就不再是抽象类了。
根据PPP,PHP5也实现了静态方法与属性。与普通的方法与属性不同,是以静态的方式存,作为类本身的一部分访问,与只存在于实例中相反。这样允许类当成是一个容器与函数与数据进行交互——从另一方面看这是对付函数命名冲突的非常有效的方法。
在PHP4中允许使用::操作符来把类中的任何方法作为静态方法调用(官方的Paamayim Nekudotayim——希伯来语,意思是“双冒号”),PHP5中把这个区分开来了,只有被static修饰的属性和方法才可以这样访问和使用。
PHP对于静态属性非常严格;如果使用->来访问静态变量或者属性(比如 $obj->propertiy)就会提示一条“strict standards”的信息和一个提示。使用非静态的方法的途径调用静态方法将会得到一个“strict standard”的消息。
class foo {
static $bar = "bat";
public static function baz() {
echo "Hello World";
}
}
$foo = new foo();
$foo->baz();
运行结果:
Hello WorldPHP Strict Standards: Accessing static property foo::$bar as nonstatic in PHPDocument1 on line 17 Strict Standard: Accessing static property foo::$bar as non static in PHPDocument1 on line 1
Siemen注,实际测试中并没有发现这个消息,只是看到了一个提示,显示说变量不存在。
有必要给静态的变量或者方法修饰作用域,如果不修饰,默认为public。
正如我们之前提到的,类可以包含方法与变量(属性)。定义一个方法就像定义一个函数一样:
class myClass {
function myFunction() {
echo "You called myClass::myFunction";
}
}
使用->指令操作符从一个类的外部调用其内部的方法:
$obj = new myClass(); $obj->myFunction();
理所当然,对象$obj是唯一能够访问类内部代码的途径——可是,如果我们想在类内部调用自己的方法应该如何做呢?可以这样:
class myClass {
function myFunction() {
echo "调用了myClass::myFunction";
}
function callFunction() {
// ???
}
}
很明显,callMyFunction()需要一种可以在类内部调用myFunction()的途径。根据这类需求,PHP中定义了一个特殊的变量$this;这个变量在对象内部,永远指向本类:
class myClass {
function myFunction($data) {
echo "The value is $data";
}
function callMyFunction($data) {
// 调用myFunction()
$this->myFunction($data);
}
}
$obj = new myClass();
$obj->callMyClass(123);
结果就是“The value is 123”。