一是对象的缓冲。如我们所知,很多设计模式都依赖于对象的缓冲机制,对于需要频繁应付大量并发的服务端软件更是如此。因此,对象缓冲的缺失,理论上会极大地降低速度。但是,由于PHP本身的定位和工作机制等原因,它在实际工作中的速度非常快。就作者自己的经验来看,在小型的Web应用中,PHP至少不比Java慢。
在大型的应用中,为了榨干每一分硬件资源,即使PHP本身足够快,一个优秀的对象缓冲机制仍然是必要的。在这种情况下,可以使用第三方的内存缓冲软件,如Memcached。由于Memcached本身的优异特性(高性能,支持跨服务器的分布式存储,和PHP的无缝集成等),在大型的PHP应用中,Memcached几乎已经成为不可或缺的基础设施了。比起使用PHP语言自己实现对象缓冲来,这种第三方解决方案似乎更好一些。
二是数据库连接的缓冲。对MySQL,PHP提供了一种内置的数据库缓冲机制,使用起来非常简单,程序员需要做的只是用mysql_pconnect()代替mysql_connect()来打开数据库而已。
PHP会自动回收被废弃的数据库连接,以供重复使用。具有讽刺意味的是,在实际应用中,这种持久性数据库连接往往会导致数据库连接的伪泄漏现象:在某个时间,并发的数据库连接过多,超过了MySQL的最大连接数,从而导致新的进程无法连接数据库。
但是过一段时间,当并发数减少时,PHP会释放掉一些连接,网站又会恢复正常。出现这种现象的原因是,当使用pconnect时,Apache的httpd进程会不释放connect,而当Apache的httpd进程数超过了mysql的最大连接数时,就会出现无法连接的情况。因此,需要小心地调整Apache和Mysql的配置,以使Apache的httpd进程数不会超出MySQL的最大连接数。在某些情况下,一些有经验的PHP程序员宁可继续使用mysql_connect(),而不是mysql_pconnect()。
就作者所知,在PHP未来的roadmap中,对于工作模型这一部分,没有根本性的变动。这是PHP的缺点,也是PHP的优势,从本质上说,这就是PHP的独特之处。因此,我们很难期待PHP在近期内会对这一问题做出重大的改变。但是,在对待这个问题带来的一系列后果时,我们必须谨慎应对。
数据库访问接口
长期以来,PHP都缺乏一个象ADO或JDBC那样的统一的数据库访问接口。PHP在访问不同的数据库时,使用不同的专门API。例如,使用mysql_connect函数连接MySQL,使用ora_logon函数连接Oracle。平心而论,这种方式并没有象我们想象的那样麻烦。
在真实项目中,把系统从一种数据库完全迁移到另一种数据库的要求是比较少见的,特别是对于LAMP这样的小型项目而言。而且,只要将访问数据库的代码进行了良好的封装,迁移的工作量也会较少。另外,使用专门API,在效率上多少会有一些优势。
虽然如此,PHP的开发人员仍然在努力构建PHP的统一的数据库访问接口。从PHP 5.1开始,PHP的发行包内置了PDO(PHP Data Objects,PHP数据对象)。PDO具有如下特性:
 统一的数据库访问接口。PDO为访问不同的数据库提供了统一的接口,并且能够通过切换数据库驱动程序,方便地支持各种流行的数据库。
 面向对象。PDO完全基于PHP 5的对象机制,因此区别于基于过程的专用API。
 高性能。PDO的底层用C编写,比起用纯PHP开发的其他类似解决方案,有更高的性能。
一个典型的PDO应用如下例:
$pdo = new PDO("mysql:host=localhost;dbname=justtest", " mysql_user ", " mysql_password");
$query = "SELECT id, username FROM userinfo ORDER BY ID";
foreach ($pdo->query($query) as $row) {
echo $row['id']." | ".$row['username']."<br/>";
}
PME模型
在大规模的程序设计中,组件(component)已经成为一种非常流行的技术。常见的组件技术都基于PME模型,即属性(Property)、方法(Method)和事件(Event)。
基于PME的组件技术可以方便地实现IoC(Inversion of Control,控制反转),是从IDE的plugin到应用服务器的“热发布”等许多技术的基础。
PHP从版本5开始,大大完善了对OO的支持,以前不能被应用的许多pattern现在都可以在PHP5中实现。因此,是否能够实现基于PHP的组件技术,也就成了一个值得讨论的问题。
下面对PHP对于PME模型的支持,逐一进行讨论:
 属性(Property)
PHP并不支持类似Delphi或者C#的property语法,但这并不是问题。Java也不支持property语法,但是通过getXXX()和setXXX()的命名约定,同样可以支持属性。
PHP也可以通过这一方式来支持属性。但是,PHP提供了另一种也许更好的方法,那就是__set()和__get()方法。
在PHP中,每一个class都会自动继承__set()和__get()方法。它们的定义如下:
void __set ( string name, mixed value )
mixed __get ( string name )
这两个方法将在下列情况下被触发:当程序访问一个当前类没有显式定义的属性时。在这个时候,被访问的属性名称作为参数被传入相应的方法。任何类都可以重载__set()和__get()方法,以实现自己的功能。
如下例:
class PropertyTester {
public function __get($PropName) {
echo "Getting Property $PropNamen";
}
public function __set($PropName, $Value) {
echo "Setting Property $PropName to '$Value'n";
}
}
$Prop = new PropertyTester();
$Prop->Name;
$Prop->Name = "some string";
类PropertyTester重载了__set()和__get()方法,为了测试,仅仅将参数打印输出,没有做更多的工作。测试代码创建了PropertyTester类的实例,并试图读写它并不存在的一个属性Name。此时,__set()和__get()相继被调用,并打印出相关参数。它的输出结果如下:
Getting Property Name
Setting Property Name to 'some string'
| 共分4页 [1] [2] [3] [4] |