您的位置:首页 > 运维架构 > 网站架构

新浪xweibo代码架构分析(二次开发)

2012-03-17 11:41 423 查看

框架概要与特色

xweibo使用MVC结构,但VC层任务分离不明显,V层也完成部分C层的任务(调用model层获取数据)。

没有使用smarty模板类,视图采用组件的形式,可以任意拼装,可以方便模板模块的复用,可以通过后台修改显示细节。

core文件作为所有调用的入口,使用的所有类,函数,适配器,都是用core提供的函数和类进行调用,便于集中控制。

对于sina open API调用有统一错误处理,通过core层提供的数据交互组件,集中对数据进行缓存,过滤,格式化等操作。

框架整体流程图





如图所示
1 请求到达后首先进入预处理模块。
2->3->4 预处理调用控制器层的类中的函数对xweibo全局数据进行设置(如session)。
5->6->7 应用初始化,如模板皮肤,应用安装位置,log位置格式,ip过滤等操作,并调用model层,设置用户的相关信息。
8->9 路由层,将用户请求交给相应的控制器(controller)进行处理。
10->11->12->13 控制器调用open api获取相关数据。
14->15->16->17 控制器缓存相关数据或者获取缓存的相关信息,或者站点数据库内定制的信息(结果显示数量等)。
18 控制器包含相关模板(view)进行显示。
19->20->21->22 每个模板(view)包含自己需要显示的组件(子view),每个组件调用model层获取自己所需的数据,进行显示。

xweibo介绍各个子功能和模块

预处理模块

用户请求进入后,可以指定加载预处理模块,这些预处理模块就是执行一些controller中的成员函数,比如初始化站点信息,比如检验用户是否登录。加载预处理模块时可以指定哪些请求跳过预处理模块,比如登录请求就不需要加载登录校验模块。

初始化操作

初始化操作,初始化工作包括如下:
1.应用配置:log日志格式,获取程序的安装位置,是否来自ajax请求,等等。
2.访问控制检测,过滤预定义的ip或请求路由(不允许直接请求的controller)
3.初始化模板皮肤
4.执行用户定义的预处理模块

路由层

路由层,根据路由配置获取请求参数中相应的变量,加载相应的php文件,实例化相应的类,并将请求其他参数传入,如果访问地址无效,执行function中的error404函数。

控制器

在项目controllers目录下的所有文件为xweibo的控制器代码。
XWEIBO中的控制器按功能分为两种,一种是作为预加载模块,在初始化过程中调用,如account.mod.php.另一种是请求通过路由层,进入控制器,调用控制器的相关方法获取数据,显示相关的模板(VIEW)。

以微博广场为例: http://apptest/xweibo_upload/index.php?m=pub 则会进入pub.mod.php,当没有指定action时候默认调用控制器的default_action(),获取数据并包含相应模板页。

微博广场上的随便看看标签url, http://apptest/xweibo_upload/index.php?m=pub.look 该url指定了pub控制器的,其action为look.调用pub.mod.php的look方法,获取数据,包含相应模板。

控制器|钩子

对于控制器的每一个方法,在执行前和执行后会执行钩子函数。即调用方法前执行 “_before_方法名()”,在调用方法后执行“_after_方法名( )” 函数。例如在pub.mod.php的look方法前,会执行_before_look()方法,执行完look方法后,会再执行一个_after_look()。提供钩子方法的好处是:当需要时候可以对数据做预处理或者当函数执行完后,根据已经获取的数据选择性的执行相应操作。

TIPS:

可能存在疑问是,那无论预处理或者调用后处理都可以在函数里执行或者加判断,为什么用钩子?

我的理解是,有些方法会被其他方法或者其他类显式的调用,如果在方法中增加额外代码会影响使用该方法的其他类,使用钩子方法,可以只在用户请求控制层的时候执行相应的钩子操作,钩子调用可以在cfg.php中关闭。

模板(view)

在templates/default目录下的所有*.tpl.php文件都是模板文件。

xweibo controller层与VIEW层,在任务分配上界限不明显。这体现在VIEW层也可以调用model层的操作获取、组织、过滤相应数据,当然获取完数据后需要对获取的数据进行显示,使用html+php混合的写法。

TIPS

XWEIBO没有使用模板引擎很大原因,是因为它想让数据组织和显示更自由化,从哪获取,显示什么样子在一个模板文件里可以更改,一个模板文件可以被其他文件包含,实现相应模块。如果使用模板引擎,在调用核心文件(core)提供的方法上不自由,另外所有的模块在使用模板引擎情况下,按照使用习惯应该再拆成两部分一部分组织数据(php文件),一部分显示数据(tpl模板文件)。并将所有组织数据部分放到controller部分。

MODEL层

XWEIBO的model层是modules下的所有文件,提供数据库、缓存、open api等数据获取或改写操作。

例如需要从open api获取数据,需使用modules目录下xwb.com.php类中的getPublicTimeline方法。

1
$list
= DR(
'xweibo/xwb.getPublicTimeline'
,
''
, null, false);
即调用modeles目录下 xweibo目录下的xwb.com.php文件中的getPublicTimeline方法。model层可以调用class或者function或者adapter目录下的相应函数或类来实现数据处理。

核心文件(core)

核心文件其实提供调用其它公用类(class文件夹下)、公用函数(funciton文件夹下)、model层函数(module文件夹下)的统一入口。提供所有实例的管理,单实例缓存,操作适配器选择,公用数据类(USER)的维护.
常用方法如下:
DS函数
调用形式:DS(‘xweibo/xwb.getUnread’);
调用module下xwb类的getUnread方法,出错后直接处理,跳转到相应错误处理页面。
DR函数
调用形式:$res = DR(‘xweibo/xwb.getUnread’);
调用后,如果出错后,不直接处理,而是将错误返回,由用户做相应处理。
DR与DS其实就是相当于提供了调用model层的统一入口。出错或者不出错的判定由xweibo做了统一判定处理。实际上这两个函数是两个宏,为了使用方便的缩写,实际上是调用了CORE文件中的数据交互组件管理类dsMgr来进行处理。
TIPS:使用数据交互组件dsMgr好处?
正常使用情况下,我直接建立类的实例,进行相应的数据请求就可以了,如果只是出错处理是否返回问题,无法再传一个参数罢了。数据交互组件好处除了错误统一处理外,还封装了对返回数据处理。因为model层的请求有的是数据库,有些是API,所以对于返回数据可能需要做额外的处理,比如说缓存,比如说数据过滤,数据格式化。如果没有这个组件,那么API的相关操作,数据库相关操作,每一个都要对数据单独做缓存、过滤、格式化等处理。

CORE文件|适配器

使用方法:

1
define(
'HTTP_ADAPTER'
,
'curl'
);
2
$this
->http = APP::ADP(
'http'
);
ADP适配器实际将一些可选的操作类或者平台相关操作类封装了。

以http适配器为例,adapter/http/目录下的所有类都提供了相同的方法,无论适配器选择了哪个类,调用时候都返回相同的结果,只不过curl_http库使用了curl库,fsockopen_http使用的是自己拼装的http数据。sae_http应该是在sae平台上使用的http库。

TIPS

这里xweibo有一个我感觉可以调整地方,这里适配器都是使用常量定义的,如果我在项目中需要根据某些判定条件动态改变适配器,只能在宏定义那做判定,不方便,或者跳过ADP函数自己建一个操作类实例。感觉xweibo开发人员可以调整下。

CORE文件|用户类

XWEIBO为用户的数据和操作单独抽象了一层,提供了公用的方法,具体的操作代理给具体的类进行操作。
举例说明:
需要获取用户UID的信息,只需要调用,USER:uid(),具体如何获取用户uid,是从session还是cookie还是数据库,memcache,这些可以代理类实现。xweibo提供了一个用session保存用户信息的clientUser类在class目录下。在我们项目中,我们将代理类改成使用cookie加密保存用户信息,只需要重新建立一个cookieClientUser类,提供相同的方法,在USER类初始化时候,换成实例化cookieClientUser类即可。
Tips

其实在功能上来看这个用户类实际上应该算是model,提供和封装了针对用户的数据交互,不清楚xweibo设计人员为什么将它提到core这层来。core的文件已经很大(2200行),如果修改出现问题会对所有访问照成影响。另外其实建议对与完成实际用户操作的类,也提供一层适配器操作,这样开发用户可以定制自己的用户操作类,无论是session或者cookie或者session服务器等等。

CORE文件|APP类

是xweibo的核心类,提供了建立和调用其他类入口

1
function
N(
$oRoute
)
//根据路由,获取一个类实例
2
function
M(
$mRoute
)
//执行一个模块(包括对应钩子函数)
3
function
&O(
$oRoute
)
//获取一个单例,调用后缓存对象
4
function
F(
$fRoute
)
//根据路由调用funciton目录下的函数
5
6
function
V(
$vRoute
,
$def_v
=NULL,
$setVar
=false)
CORE|TPL类/IO类/cache类
提供了模板类,但模板只是将assign的变量转化为global,然后在display前,将全局的变量转化成局部变量,在模板所对应的文件直接使用。

1
extract(
$GLOBALS
[V_GLOBAL_NAME][
'TPL'
]);
提供了统一的IO操作,使用IO类来执行文件读写,增删等操作。
提供了统一缓存操作,通过适配器可以选择文件缓存,memcache缓存,目前xweibo主要缓存了,用户一些配置信息,比如皮肤一类的信息,调用API显示表示需要缓存数据,可以设置缓存时间。

小结

感觉xweibo提供了一个完整的微博内容展示框架,内容以组件的形式表现,可以层层拼装,包含,模板在可复用性极强。提供了简单的管理后台,允许用户对显示规则进行定制,也方便二次开发。提供了完整的缓存策略,提供了对API封装和访问出错处理控制。提供了微博相关的各种实用函数和类,比如内容的format(文本中出现@等替换成链接),加解密处理(des),http的curl封装等等。
但就我个人使用感觉上,还有细节上需要改进的地方,比如说现在的类和函数这块应该也提供适配器,拿openapi举例,现在的第三方应用的api调用形式,根据需要各有不同(如认证),用户对于各种类的使用也各有不同,比如说format。虽然说放弃了smarty可以减少文件的层次(数据组织和显示),但前端开发人员可能更习惯于使用模板类,建议将templates下的所有模板再拆分两层,一层放到controller,一层完全是smarty模板(想办法也能继续使用plugin函数)。细节上把一些能公用的小功能再抽出来成一个util类,比如oauth文件里的对http_query头的封装,就可以单拿出一个静态函数。另外感觉xweibo为了兼容sae也加入不少代码,虽然通过配置一点不影响使用,但查看代码时候会遇到很多平台相关判断,开发者体验上怪点。感觉上如果人手充足针对sae平台单独设计优化,对外提供一个纯净版本的,呵呵,以上都是个人意见,对于xweibo自己也有很多地方要学习,很好很强大,第三方开发的好框架。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: