PHP中插件机制的一种实现方案

这篇文章的出发点是我对插件机制的理解,及其在PHP中的实现。这套插件机制已经在你目前看到的这个博客程序中的重构代码中实现(我定名为STBlog),由于尚未开发完毕,所以目前暂不开发源代码。但文章会涉及到核心思想和部分实现代码。

插件,亦即Plug-in,是指一类特定的功能模块(通常由第三方开发者实现),它的特点是:当你需要它的时候激活它,不需要它的时候禁用/删除它;且无论是激活还是禁用都不影响系统核心模块的运行,也就是说插件是一种非侵入式的模块化设计,实现了核心程序与插件程序的松散耦合。一个典型的例子就是Wordpress中众多的第三方插件,比如Akimet插件用于对用户的评论进行Spam过滤。

一个健壮的插件机制,我认为必须具备以下特点:

  • 插件的动态监听和加载(Lookup)
  • 插件的动态触发
  • 以上两点的实现均不影响核心程序的运行

要在程序中实现插件,我们首先应该想到的就是定义不同的钩子(Hooks);“钩子”是一个很形象的逻辑概念,你可以认为它是系统预留的插件触发条件。它的逻辑原理如下:当系统执行到某个钩子时,会判断这个钩子的条件是否满足;如果满足,会转而先去调用钩子所制定的功能,然后返回继续执行余下的程序;如果不满足,跳过即可。这有点像汇编中的“中断保护”逻辑。

某些钩子可能是系统事先就设计好的,比如之前我举的关于评论Spam过滤的钩子,通常它已经由核心系统开发人员设计进了评论的处理逻辑中;另外一类钩子则可能是由用户自行定制的(由第三方开发人员制定),通常存在于表现层,比如一个普通的PHP表单显示页面中。

可能你感觉上面的话比较无聊,让人昏昏欲睡;但是要看懂下面我写的代码,理解以上的原理是必不可少的。

下面进行PHP中插件机制的核心实现,整个机制核心分为三大块:

  • 一个插件经理类:这是核心之核心。它是一个应用程序全局Global对象。它主要有三个职责:
    • 负责监听已经注册了的所有插件,并实例化这些插件对象。
    • 负责注册所有插件。
    • 当钩子条件满足时,触发对应的对象方法。
  • 插件的功能实现:这大多由第三方开发人员完成,但需要遵循一定的规则,这个规则是插件机制所规定的,因插件机制的不同而不同,下面的显示代码你会看到这个规则。
  • 插件的触发:也就是钩子的触发条件。具体来说这是一小段代码,放置在你需要插件实现的地方,用于触发这个钩子。

原理讲了一大堆,下面看看我的实现方案:

»阅读全文

Tags: php,stblog,插件

22周岁

这是我第一个在海外度过的生日,虽然没有什么特别活动,但仍然收到了家人、朋友和众多同学的祝福,真的是非常感谢和感激。

这让我觉得,虽孤身一人求学,但却并不孤独。

服务器正在升级

难怪前些天我总感觉服务器不稳定(经常掉包,反映缓慢),原来是真的出问题了。今天IXWebhosting发邮件告诉我,下周可能对我目前博客所在的服务器做迁移,以提供更好的服务。

国外的IDC服务客户服务真的是没话说,就算是他们的问题,你也很难找出埋怨的理由。国内大部分IDC就比较无良了,我用过很多IDC的主机服务,大部分给我的感觉就是:交款前你是他的上帝,交款后他是你的上帝。

We have been alerted to the fact that life on your server has not been so great. Load times are slower than they should be, some downtime may be experienced, or uploading content to your sites is not the quick and easy process it once was. If you have no idea what I'm talking about, that's great...but you may become acquainted with these symptoms soon if we don't do something about it now.

What we have decided to do is migrate accounts away from your server in order for the quality of life to improve across all accounts. Your account may be migrated (and if it is, what to expect is outlined below) or you may remain on your current server. Either way, you should notice a marked improvement in performance!

Migrations will begin on Monday, September 21st and continue through Friday. If your account is one of the ones being migrated, you will receive a ticket in the helpdesk informing you that the process has been initiated and what to expect.

These changes are being made so that you may experience much higher-quality service levels – the service levels you signed up for.

建议国内的IDC们学习下这种24*7无缝无掉线的客户服务吧。

Location-aware Query Processing

这是我今天做的一个关于Location-aware Processing的Presentation,立此存照。

Location-aware是近5年来,业界发展最迅猛的一个新兴概念和技术。Google Maps on Mobile就是这一技术的典型应用。

PPT看这里

图标吾爱搬到了新家

再次对图标吾爱进行了整体优化,上次优化主要集中在搜索算法和程序逻辑

此次优化主要集中对前端的优化,严格遵循Yahoo优化小组的这34个标准。由于涉及到大量的JS/CSS文件,所以优化的效果非常明显,YSlow给出的图标吾爱首页的评分是95。

另外,我将图标吾爱从IXWebhosting搬到了国内的易联主机。由于目前身处国外,暂时感觉不到有多少明显的变化,请国内的朋友帮忙测试下网站的响应速度。IXWebhosting最近似乎不是很稳定,经常出现掉包的现象,而且MySQL数据库反映缓慢(也有可能是我的网络的原因)。

说来很有意思,一个对设计并不擅长的代码工人现在却做了一个对设计要求比较高的图标搜索站。我也不知道自己对这个站的愿景是什么,也不对它的发展抱多大的期望,但是我总希望自己能够为国内UI和UED的发展做出些什么,虽然我只是个程序员:)

在未出国之时,我就发现国内的网站相比国外,普遍不重视网站的User Interface、Web Accessibility和Web Usability。到了国外,这种感觉就更加强烈了,就拿银行业的网站来说,国内有多少个银行网站能够兼容所有主流浏览器的?似乎很少,于是就有了用户为了使用网银而特地打开一个IE浏览器的笑话。再比较一下国内某著名航空公司澳洲某著名航空公司网站的界面设计和用户体验,你就不难发现其中的差距。

而我认为,图标作为Web设计中重要的一个细节,对UI设计应当有相当大的改善和促进作用。很多时候,一个图标的有效表达可抵千言万语。

额……似乎写着写着就跑题了,就到这里吧。

Tags: icon52

卫报的网站技术架构

这是QCon 2009伦敦站,由英国卫报的首席系统架构师Mathew Wall带来的演讲,非常具有借鉴和学习意义。

卫报的R2架构是一个典型的J2EE敏捷开发的实际应用,也是一个企业级的网站从旧的系统(卫报R1)移植到新的系统(R2)的典型实战。

R2的初步应用架构:

可以看到,这是一个典型标准的J2EE敏捷开发架构:

1、采用原生Spring MVC作为Web Tier;

2、使用Velocity 1.5做模板引擎;

3、使用Hibernate ORM做持久层。

4、建立实体Domain Model和其对应的Repository。

6、使用Ehcache配合Hibernate进行缓存

除架构值得学习之外,Mathew还介绍了他们的一些新老系统移植经验,比如,在移植过程中为何首先卫报的Travel频道作为测试对象,以及在这过程中碰到的问题和解决方案。

非常值得一看的视频:http://www.infoq.com/presentations/evolving-architecture-guardian-uk

Tags: 架构,j2ee

使用PHP/gzip压缩网站JS/CSS文档的实例

一些泛WEB 2.0网站为了追求用户体验,可能会大量使用CSS和JS文件。这就导致在服务器带宽一定的情况下,多用户并发访问速度变慢。如何加快网页响应速度?解决办法之一就是:依照Yahoo性能优化小组提出的N条性能优化建议对前端程序进行优化和重构,关于此文的讨论很多,在这里不再赘述。

这篇文章主要分享一下我个人在实际项目中,对于使用PHP对JS和CSS进行压缩的经验,在这里假设服务器仅支持GZIP压缩,不支持.htaccess(符合很多站长的租用的虚拟主机实际情况)。

首先说说对CSS和JS文件进行性能优化的几个小技巧:

  • 将多个CSS/JS文档合并成一个文件,以减少HTTP请求
  • 对合并后的文件进行文档压缩,比如分别使用js compressorCSS compress
  • 如果使用到一些主流的JavaScript框架,比如JQuery, Mootools或者YUI,强烈推荐直接使用Google AJAX Library以外部链接的形式导入基库。
  • 最后,就是本文所提到的,使用GZIP在服务器端对JS/CSS文档进行压缩。

这里提到的方法对系统来说是无侵入式的,也就是说不管你的程序是新编写的,还是已经上线了很久,均适用。

»阅读全文

Tags: php,gzip

[案例]iptables/netfilter建立防火墙之常用命令集锦

声明:本文由cnSaturn.com原创,转载请注明出处。

Update: 2009-8-25

本文的目标读者是已经了解过iptables运行原理的同学,如果你连iptables是什么都不知道,那么本文并不适合你。因为此文并不介绍iptables的运行原理,而是直奔主题介绍一些它的常用实施案例。

iptables/Netfilter可以用来在Linux主机环境下架设简单的防火墙。

现在,假设我们有一个IP段为192.168.1.0/24的内部子网,它通过一个网关(gateway)链接到外部网络(可能是互联网或其他子网)。我们的需求是:需要通过iptables为其配置一个简单的防火墙以满足特定的需求。以下所有案例均基于此假设,网络拓扑图如下:

案例一:拒绝外部网络的所有FTP数据包,但允许内部子网运行FTP服务。

»阅读全文

Tags: linux,iptables

贴几张年初去企鹅岛的照片

这是今年年初,我和朋友一行四人游至墨尔本著名的景点企鹅岛的一些照片。今天翻自己的硬盘,突然发现了这些照片,于是贴上来立此存照。

Phillp Island,又称企鹅岛,距离墨尔本大约三个小时左右的路程,应该是南半球最容易看到企鹅的地方。这些小企鹅(这种企鹅的名字就叫做"小企鹅")只在澳大利亚和新西兰部分地区出没。

这不是壁纸

初到澳大利亚时,我就感觉这个国家的生态真是一绝,比如什么东西长得都很大:比姚明还高的仙人掌,近1米高的西芹……风景那更是没得说,比如下面这张照片,是我们经过企鹅岛时GPS发生错误引导而“偶然发现”的一处海滩。

深处其间,反复置身天堂。Paradise.

我的背影……

低低的云朵

天渐渐暗下,到处都是海鸥在我们头上盘旋。

企鹅马上就会成群结队的出没了,可惜的是,全场禁止拍照。这不能不说是一个遗憾,但为了保护这些可爱的小精灵,也值了。不过朋友倒是照了几张陈列馆的企鹅模型。

照片中左手第二个就是我们这次看到的小企鹅,非常小。大概只有不到30厘米高。再次感叹大自然的伟大与人类的渺小。

不贴我本人的照片似乎不太厚道,哈哈。不过我不告诉大家这里面哪个是我,大家可以通过对比上面的“我的背影”猜猜看。

完结。

PHP设计模式:Singleton单例模式

此文承接之前我在PHP中实现简单工厂抽象工厂的讨论,讨论一个广泛应用在OOP体系中的设计模式——Singleton模式。

Singleton Pattern(中文称单例模式),可以说是最容易理解的设计模式了,也充分体现了DRY (Don't Repeat Yourself)的思想。它的核心思想是:保证一个对象存在且仅允许存在一个实例,并提供一个全局访问方式[via]。

单例模式的运作模型是:当对象第一次被请求时,创建这个对象的实例;之后的每次请求,仅传递已创建实例的句柄。与单例模式相对应的模式叫做Prototype(Java平台下)或者叫SingleCall(.NET平台下),在此种模式下,每次请求一个对象,都将新建一个实例。

在WEB程序中应用单例模式的一个典型例子是数据库连接的创建:通过数据库句柄来连接数据库这一行为是独占的。换言之,在一个句柄尚未关闭之前,你无法第二次创建一个相同名称的句柄。然后在日常编码中,假设你希望在同一页面中操作由数据库传递回来的多组数据。此时如果采用传统的Prototype方式编程,为了程序的安全运行,你可能需要创建多个数据库链接句柄或者重复进行打开/关闭数据库连接的操作。显然,这样的操作会导致程序过度消耗一些不必要的资源。

在此场景下,我们可以运用单例模式来维护和共享同一个数据库句柄。优点有二:

1、提高了程序运行上的安全性。你不必过多的担心和考虑诸如数据库打开/关闭的问题。

2、避免了因创建多个连接导致的不必要资源浪费。垃圾回收机制仅需要对一个链接句柄进行操作。

当然,以上两个问题对于PHP来说并不是问题,PHP的垃圾回收机制就是,当一个页面执行完毕会自动清空所有资源和内存,这里面就包括数据库连接。

至此,可以总结出Singleton单例模式在WEB程序中的运用场合:

1、某些资源本身具有独占性,你不希望在多个地方重复创建对这个独占资源对象的实例。

2、你需要在一个对象的多个实例之间共享这个对象的状态(下面我会将此条规则进行代码举例)。

下面写一段小代码来演示PHP 5中Singleton的实现:

/***************************************************************************
 *              Singleton在PHP5中的实现
 *             
 *   @Author  :    Saturn
 *   @Contact: http://www.cnsaturn.com/
 ***************************************************************************/
class Singleton
{
 //此成员变量用来记录此对象的引用次数
 private $counter = 1;
 //注意这里是private,即禁止外部程序通过解析函数实例化对象
 private function __construct()
 { }
 //禁止克隆这个对象
 private function __clone() 
 { }
 //必须通过此方法得到对象的引用
 public static function getInstance()
 {
  static $instance = null;
  if($instance == null)
  {
   $instance = new Singleton();
  }
  return $instance;
 }
 
 public function getUsedCount()
 {
  return $this->counter++;
 }
 
}
//test test
echo Singleton::getInstance()->getUsedCount();//echo 1
echo Singleton::getInstance()->getUsedCount();//echo 2
echo Singleton::getInstance()->getUsedCount();//echo 3
$obj = new Singleton();//trigger fatal error
?>

此程序演示的是如何通过Singleton模式让多个引用能够同时共享此对象的某个状态,在这里是共享$counter。

注意,我们将解析函数的Scope设置成了private,这样做为了禁止通过解析函数实例化对象,而必须使用对象提供的静态化方法getInstance来获取对象的引用。

这个例子比较简单,但已经初步展示了单例模式的核心思想,仅起抛砖引玉的作用。