查看文章 |
Observer在PHP中的应用
2008年03月03日 星期一 下午 04:30
作者:老王 什么样的代码算是好代码?逻辑区分清晰的代码就是好代码。可惜总有一些难啃的骨头,让我们的代码从好变坏,下面讲一个例子。 假设我们的代码是类似CakePHP风格的,其中有一个模型Article,还有一个控制器ArticlesController。 加入一些需求: 我们在ArticlesController控制器中操作Article模型的时候,如果执行了模型的save操作,那么就执行一些动作,比如说发送一封邮件,告诉老板某个文章已经保存了(老板说不定会因为这个功能而更加欣赏你)。 需求本身并不复杂,但是在哪里实现需求却让人有些头疼。 最先想到的位置是Model,因为ActiveRecord风格的Model本身一般已经存在beforeSave这样现成的回调方法,我们只要把逻辑加入其中即可,这样确实实现了需求,但是仔细想想,就会发现,需求所涉及的逻辑其实并不属于Model,毕竟诸如发送一封邮件之类的功能属于应用逻辑的范畴,而不是领域逻辑,如果强行把应用逻辑加入Model里,会让Model的复用性大大降低。那么直接在Controller里编码实现如何呢?也不好,因为我们可能在多个控制器里都需要编写类似的代码,甚至一个控制器的多个动作也可能都需要编写类似的代码,这时硬编码就会造成重复,虽然我们可以通过提取公共类等方法来尽量避免重复代码,但是仍然感觉不爽,毕竟这样的实现太生硬,不够透明。 。。。。。。 别担心,observer驾着五彩的云朵来救我们了: 注:下面仅部分代码和observer相关,时间关系,请读者自行区分。 abstract class Model { protected function beforeSave() { - 1; $i >= 0; $i--) { $model = new $name; 'ArticleObserver'); ================================================== 补充后记 经过一些思考,发现目前的Observer实现方式存在硬伤:仅适合CakePHP风格的MVC结构,但CakePHP本身又不是一个严谨的ActiveRecord实现,比如说CakePHP的find方法是对象调用,而传统意义上的ActiveRecord模式中,find方法是一个静态调用,这就造成了不可调和的矛盾,导致我们在控制器里无法使用__get对模型访问进行拦截。如果想在传统意义上的ActiveRecord模型中使用Observer,目前或许只能在控制器调用模型的时候,手动addObserver了。 |
最近读者: