正在查看: Saturn 所写的文章(第 5 页 / 共 54 篇)

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

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

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

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

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

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

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

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

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

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

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

»阅读全文

Tags: php,stblog,插件

CodeIgniter上传类库的一个Bug

这几天重构博客程序的时候,发现了一个CodeIgniter默认上传类的BUG。很奇怪的是,一直到前些天CI官方最新发布的1.7.2,此BUG仍未修正,特此记录。

症状:只能上传图片后缀的文件,其他类型文件(比如.zip,.tar.gz)无法通过验证,就算你将这些类型添加进了$config['allowed_types']。

涉及到的CodeIgniter版本:1.7.1;1.7.2。

原因:Upload Class中的is_allowed_filetype()方法有逻辑错误。

解决方案

1、如果你不想动CI的系统源码,那么就将除图片类型之外的其他后缀,放到图片类型之前,比如:

$config['allowed_types'] = 'zip|gz|png|gif|jpg';(正确)

$config['allowed_types'] = 'png|gif|jpg|zip|gz';(错误)

请注意以上暗红色部分的位置。

2、对Upload.php开刀并修改is_allowed_filetype()的判断逻辑,解决办法在这个帖子里面:

http://codeigniter.com/forums/viewthread/113029/

这个BUG在BUG Tracker存在了那么久,开发者竟然不采纳的……What can I say?

服务器正在升级

难怪前些天我总感觉服务器不稳定(经常掉包,反映缓慢),原来是真的出问题了。今天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无缝无掉线的客户服务吧。

胡言乱语之一

这是我的胡言乱语系列的开篇文章,主要记录自己日常中因为某些事件而“触发”的一些想法。如果有人赞同,那固然很好;如果没有,权当练习写作和思维;若干年之后看这个系列应该会感觉很有意思。

总之,欢迎拍砖与探讨。版权的,没有;拷贝的,欢迎。

#1 寂寞的中国互联网

国内现在有个很搞笑的现象,当国内媒体热衷报道国外的创新性互联网产品如Twitter时,郁闷的网民却发现这些网站根本就访问不了。于是乎,此类新闻就彻底沦为炒作和噱头,只是不知道这些炒作的对象是谁?

不过这还是有好处的,至少它给了一小撮模仿起家的翻墙精英以机会。因为只有他们,能够第一时间翻过墙去,COPY那些国外的先进理论。然后就有了非死不可中国版人人网,推特中国版(现在仍然被维护)的饭否们。

国家一直鼓励创新,尤其是在互联网这个人才辈出的新兴行业。但在目前这个并不开放的互联网大环境下,何以创新,以何创新?或许,大部分创新已经都被扼杀在了它们的初级阶段了。

没有一个开放的环境,在我看来,很难出现百花齐放的创新性互联网。

#2 没落的博客

志勇兄博文《流量》一文再次引发了我对国内独立博客未来的思考。我这里所谈到的博客,是指独立架设博客,非第三方BSP新浪博客之流,那里是炒作、绯闻以及“名人”之间骂战的起源地。当然不能一棍子打死一船人,但总的来说,我给新浪博客下的定义是“名人博客”:80%的草根给20%的“名人”捧场吆喝。这又一个墨菲法则的典型案例。

在国内写博客真的是一件吃力不讨好的事情。首先,你很难因此赚到钱,就算赚到钱也很难以此糊口。其次,你需要时不时担心自己的某些文字是否触犯了神秘机构“有关部分”的潜规则,进而被悄无声息的拔掉网线?就算你将服务器迁至国外,你也要承担被GWFed的风险……

在我看来,这都不是目前博客没落的最大杀手;最大杀手是对版权的藐视,这可以说是中国互联网的特色之一。想必大多数写博客的人都碰到过这样的情况:你花了大半天写完了一篇博客文章,第二天却欣喜的发现这篇文章只字未改的出现在某知名网站上,只是作者变了个人。

于是乎,博客作者们仅剩的一点动力也被无情的扼杀了。所以,下次你发现一个博客几年没有更新,千万别惊讶。

开放与尊重,是博客价值体系的基石,破坏了它,想不没落都不行。

»阅读全文

Tags: 胡言乱语

实例分析setTimeout和setInterval的区别

理解编程中某个对象、方法和属性的最好方法,莫过于通过不同实例对其进行验证。

在JavaScript中,setTimeoutsetInterval是window对象的两个不同方法;我们通常利用这两个方法来重复执行某个代码段或者function,以实现网页上的一些“动态”效果。

有意思的是,它们的用法几乎完全一样,都是:

setTimeOut(expression, timespan)

setInterval(expression, timespan)

第一个参数expression是需要调用的function;第二个参数timespan是指定延迟(等待)多少秒才调用参数一中的表达式,单位是微秒milliseconds。

既然这两个方法都是延迟一段时间后执行某个表达式,那么,它们的功能不就一样了吗?用我们的膝盖想想都应该知道,如果这两个方法的功能完全一样, ECMAScript开发组何不将他们合并成一个方法?

»阅读全文

Tags: javascript

Hello, Stblog

时间过的真快,来墨尔本已经一年多了,而距离我写的上一篇日志也有半年多了。这段时间感悟很多,有一堆东西想写下来,不过还是手懒了。

目前你所看到的这段文字,来自我和CI中国其他几位成员目前正在开发的基于Codeigniter (PHP MVC框架)开发的一套博客程序——Stblog,目前的最新版为 v0.1.2。写这套程序的原因,我写在了这里,就不转载过来了。

正在学习PHP和Codeigniter的朋友,我推荐你们下载和试用这套程序,但目前暂不推荐使用在真实的环境当中,因为它有诸多地方需要完善。待程序和相关文档成熟之后,在使用也不迟。

Stblog开发相关动态:

项目主页:http://code.google.com/p/stblog/

程序下载:http://code.google.com/p/stblog/downloads/list

Bug提交:http://code.google.com/p/stblog/issues/list

安装方法/插件/主题开发教程:http://code.google.com/p/stblog/w/list

注意:STBlog的协作开发和版本控制工具为Git (没有使用SVN),目前被托管在Github.com。请移步 http://github.com/stblog/Stblog  了解最新开发动态,以及checkout最新开发版本。

在PHP中数组进行二分法查找

二分法查找(Binary Search)是一种搜索算法(平均的时间复杂度为O(log n)),支持对一个有序列表中的某个元素进行快速查找。更多二分法查找的解释和例子可以参考维基百科的说明

这里我只写出其在PHP中的算法实现,仅作记录。如果你有更好的实现方法,请在下方留言与我交流。

//script by Saturn from cnsaturn.com

function binarySearch($searchArray, $targetValue)
{
    //初始范围为全部数组
    $startIndex = 0;
    $endIndex = count($searchArray) - 1;
    //初始中间位置的元素索引
    $middle = round(($endIndex - $startIndex) / 2);
 
    //如果要搜索的元素在初始开始位置,则直接返回
    if($targetValue == $searchArray[$startIndex])
    {
       return $startIndex;
     }
 
    //如果要搜索的元素在初始结束位置,则直接返回
    if($targetValue == $searchArray[$endIndex])
    {
       return $endIndex;
    }
 
    //循环查找
    while($searchArray[$middle] !== $targetValue && $startIndex < $endIndex)
    {
       //调整搜索起止范围
       if($searchArray[$middle] > $targetValue)
       {
          $endIndex = $middle;
       }
       else if($searchArray[$middle] < $targetValue)
       {
          $startIndex = $middle;
       }
  
      //调整中间位置元素的索引,注意获得索引值的方法
      $middle = round(($endIndex - $startIndex) /2) + $startIndex;   
   }
 
   //返回目标值的索引,如果未找到则返回-1
   return ($searchArray[$middle] == $targetValue) ? $middle : -1;
}

创建一个数组和一个目标值来测试上述查找算法:

$array = array(1,2,3,4,5,6,7,8);

//echo 4;
echo binarySearch($array, 5);

使用PHP和Python查找100以内的所有质数

质数(Prime Numbers)就是只能被1和它本身整出的自然数。本文描述查找100以内质数的算法分别在PHP和Python中的实现,仅作记录。

PHP版查找100以内的所有质数:

<?php
//script by Saturn @ cnsaturn.com
for($i=2; $i< 100; $i++)
{
  //$count is used to check whether or not the internal loop is exhausted 
  $count = 0;

  for($j = 2; $j < $i; $j++)
  {
    if($i % $j == 0)
    {
      $count ++; 
      echo "$i = $j * " . $i/$j .".\n";
      break;
    }
  }
        
  if($count == 0)
  {
    echo "$i is a prime number. \n";
  }
}

Python版(via)查找100以内的所有质数:

for n in range(2, 10):
    for x in range(2, n):
        if n % x == 0:
            print n, 'equals', x, '*', n/x
            break
    else:
       # loop fell through without finding a factor
       print n, 'is a prime number'

可以看到虽然两种语言对质数查找的实现都比较简单,但相比PHP而言,Python更简洁,语义化更明显。

正式开始学习Python

Python之名如雷贯耳,但一直没时间来学。今天一口气看了8个小时Python的Docs,从目前的想法来看:它的表现高于我的预期。

简单,优雅,够DRY(Don't Repeat Yourself),特别适合快速开发,是我喜欢它的地方。如果将其所有优点融入Agile开发的理念中,相信会大大促进一个团队的开发效率。毕竟开发效率从做产品的角度来说,远远比其他因素重要,特别是对互联网应用。

目前唯一不太适应的是,它的“缩进即语法”这一规定,看来要花一段时间习惯。毕竟已经太过习惯.NET/PHP/JAVA这样的语法了。

print 'Hello, Python'
Tags: python

不用持久化Mysql连接(Persistent Connection)的几种情况

一直对PHP提供的持久化连接(Persistent Connection)的使用将信将疑,今天算是彻底做了个research,对其使用和应用场景清晰了很多,特此记录。

今天在CI论坛上有个帖子讨论PHP连接数据库时持久化链接的问题,我在这里做个总结 (就在写这篇文章的时候发现已经有人总结的很好了,于是直接转帖过来,没有必要重复劳动)。

以下内容来自PHP官方站点关于persistent connection的评论

不使用持久化数据库连接的诸多理由和场景:

* When you lock a table, normally it is unlocked when the connection closes, but since persistent connections do not close, any tables you accidentally leave locked will remain locked, and the only way to unlock them is to wait for the connection to timeout or kill the process. The same locking problem occurs with transactions. (See comments below on 23-Apr-2002 & 12-Jul-2003)

* Normally temporary tables are dropped when the connection closes, but since persistent connections do not close, temporary tables aren't so temporary. If you do not explicitly drop temporary tables when you are done, that table will already exist for a new client reusing the same connection. The same problem occurs with setting session variables. (See comments below on 19-Nov-2004 & 07-Aug-2006)

* If PHP and MySQL are on the same server or local network, the connection time may be negligible, in which case there is no advantage to persistent connections.

* Apache does not work well with persistent connections. When it receives a request from a new client, instead of using one of the available children which already has a persistent connection open, it tends to spawn a new child, which must then open a new database connection. This causes excess processes which are just sleeping, wasting resources, and causing errors when you reach your maximum connections, plus it defeats any benefit of persistent connections. (See comments below on 03-Feb-2004, and the footnote at http://devzone.zend.com/node/view/id/686#fn1)

参考:

Persistent Database Connections (PHP.net)

mysql_pconnect (PHP手册)