这次因为种种原因,非常幸运地开始尝试php开发,感谢领导。 很早很早就学了php语法,但一直没用过,这次终于开了php开发的svn权限,可以大饱眼福了。

公司用得是Yaf框架,Yet Another Framework。是公司年轻的技术大牛鸟哥的开源作品。 用C语言写的框架,相当于对php本身进行了重新组织,对于性能的提升是很大的据说。 另外,鸟哥的作品还有Yar,Yac等。其中Yac据说实现了无锁的MC缓存技术,可以实现的原因是公司特有的可以以uid为唯一标识单位的数据结构。 具体文档地址:Yaf框架文档

这次的开发工作主要其实就是套模板啦,毫无技术含量TAT……不过其实这不是重点,拿到了svn权限,业务逻辑的代码就可以随便看啦,所以说这次的贡献并没有多少,但是收获还是不少的。

1、首先复习了一下php语法。

语法在早些年就看过了,基本上没用过就忘了。

这次补充新的内容就是关于对象和类的。

比如:ClassName::foo 这个就是访问类的静态成员属性。不需要实例化,也不能实例化,直接当做方法使用。定义的时候要写static。

比如: abstract 抽象类。里面凡是abstract的成员,被继承的时候必须都要实现。相当于抽象类给子类们规定了一个规范,规范里的方法,子类都必须要实现。

比如:魔法方法。__set(),__get(),__call()等。它们像监听事件一样,在发生一些操作的时候,就会主动被调用。 如:__construct,叫构造函数,在初始化时调用。 对应的析构函数,在销毁时调用。

这些都在php的官方文档里用,非常好用,感觉对于类的概念有了更多一些了解。 php文档无敌=》PHP: Static(静态)关键字 - Manual

2、业务框架 yaf的流程图:

应用的目录结构主要为以下(有部分省略):

|-application  //业务逻辑
	|-controllers //继承于Controller_Abstract,主要用来实例化page类,然后渲染视图,相当于程序入口
	|-library 
		|-Controller //其中应用Controller抽象基类Controller_Abstract继承于Yaf_Controller_Abstract,提供了渲染页面,返回aj接口等共用方法
		|-Comm //封装了一些基础功能组件,如数据库管理类,BigPipe等
		|-Da //数据层抽象基类,最原始的增删改查方法
		|-Page //每个页面的业务逻辑层,可以初始化多个pl在同一页。
		|-Pl //每个pl的业务逻辑,它的抽象类继承于Comm_Bigpipe_Pagelet,对Pagelet做一些常用方法的封装
		|-Tool //封装的一些工具 
		|-Model 
	|-models //继承于Model_Abstract,这里基本作为对于Da的封装,外部增加一层业务逻辑,也就是对于数据输入输出的处理。
	|-modules //同样继承于Controller_Abstract,做业务逻辑,一般会放内部使用的方法调用,cli等。相当于一些业务逻辑的组件。
	|-plugins //存放yaf插件
	|-views //视图层,存放phtml文件,yaf支持smart模板引擎。
	Bootstrap.php //入口的引导文件,可在此进行配置一些常量,初始化插件,初始配置等。
|-conf //配置文件
	|- application.ini //定义应用程序的一些配置,下面有详解
	|- conf.ini //有mc-key格式
|-daemon //队列处理
|i18n //语言包
|-public

数据请求流程: 默认文件的命名首字母大写(原因待查)

1、application.ini: 定义应用程序的一些配置,如:

application.directory                                = APP_PATH "/application"
application.dispatcher.throwException                = true
application.dispatcher.catchException                = true
//map的意思是路由规则是map的,也就是说访问/aj/foo,会访问controller的aj文件夹下的foo文件,类名为Aj_FooContorller.
//同样,Yaf下支持多种路由规则,详见Yaf文档
application.dispatcher.defaultRoute.type             = "map"
application.dispatcher.defaultRoute.controllerPrefer = true
//分发器默认的路由访问路径为:IndexController
application.dispatcher.defaultController             = "Index"
//分发器默认的action命名:runAction
application.dispatcher.defaultAction                 = "run"
//视图文件格式
application.view.ext                                 = "phtml"
application.modules                                  = "Index,Internal,Openapi,Cli,Interface"

2、通过上面的规则,我们可以访问默认的路由,也就是直接访问域名(需要设置,此处情况是Nginx,下面会记录规则,Yaf文档有其他服务器的配置规则),就会执行controllers下的Index.php,类名为IndexController, 或者访问 http://a.com/foo,就会执行controllers下的Foo.php,类名为FooController。

默认会执行runAction(或者aaaaAction,需要在上面的application.ini中配置) 如:

public function runAction() { //some code
    $this->render_page ( new Page_Test () );
}

经过一些逻辑,最后实例化要执行的与页面对应一致的page的逻辑。 这里的Page_Test类存放在了library的Page下。 这一层相当于路由过来应用程序的入口。

3、library/Page 下的page业务逻辑

根据上面的解释,这里处理具体的业务逻辑。如上面第二步会实例化出来。

继承于Page_Abstract, 代码逻辑如下:

//最基本配置
protected $tpl = 'page/test.phtml';
protected $name = 'page_test';

//初始化的构造函数,去执行父类的构造函数
//如果页面多个pl,就把把子pl放在$children数组里,这里就一个页面,所以$children为空数组。
public function __construct() {
    $children = array();
    parent::__construct($this->name, $children);
}

//渲染页面的数据
public function prepare_data() {
    //处理返回要套在模板的数据
    return $data;
}

执行完上面的方法,就会去直接渲染$tpl这个变量存储的模板了。 这也就是说,我们可以在prepare_data里改变渲染模块 如:

$this->tpl = 'page/other.phtml';

最后就会去渲染other页面了。

去渲染页面的原理过程就是: 2里面去$this->render_page ( new $page_name () );的时候。

render_page的代码如下:在Controller_Abstract中

$render = Comm_Bigpipe_Render::create(Comm_Bigpipe_Render::detect_render_type(), $page_obj);
$render->render();

Comm_Bigpipe_Render::detect_render_type()检测渲染类型。 详见Comm_Bigpipe下,有传统型,随机渲染,流水线型。 create就是把这个类型实例化

return new $render_class($pl);//render_class即该类型

假设是传统型:Comm_Bigpipe_TraditionalRender,里面注册了enter,leave方法。 enter方法获取样式和脚本。 leave方法就是真正用模板引擎渲染页面啦。

实例化好渲染类型之后,就可以render了。 主要代码如下:

self::dfs($this->pl, array($this, 'enter'), array($this, 'leave'));

dfs深度优先遍历,执行上述的enter,leave代码,递归在中间执行。

4、views/page/test.phtml views层存放html模板,这里采用smarty模块引擎。 默认直接解开上面返回的$data数据。也就是说返回的$data[‘msg’],在页面里可以直接写<?=$msg?>

5、这样基本就是一次请求的逻辑写法。这当中的可以用到很多的工具,如Tool,Comm等等。 如 存个memCache: self::set_mc(self::$mc_key, $uid, false);

——————————————————————————

3、plugin

根据Yaf流程图,首先进入Bootstrap.php,在Bootstrap里会初始化plugin。

这里说明一下这次业务上面的一个插件,它实现了路由的配置,性能检测存储等。 它的主要思路就是去注册几个Yaf给出的流程图中几个事件点(hook)。 如:routerStartup就是处理router之前的事件。 这样可以自由控制路由规则等等业务整体相关逻辑。

4、开发过程中遇到的问题:

form表单method=”get”时,提交会忽略action里url的param参数,加上表单中input的name的值和参数

如:action="/a" 
	<input name="key" value="1"/>

会提交到/a?key=1 但action=”a?key=1”则会提交到/a 中

+++++++++++++++++++++++

这次的开发到这里结束了,时间比较短,只写了一小段php而已,不过收获很多。下面是这次的时间表。

day 1:复习语法

day 2:熟悉框架

day 3:单元测试

day 4~6:js & 实现简单接口

#Todo

5、环境配置

1、vhost 2、php-fpm.conf 3、fpm.d 4、nginx fpm是fastCgi在php上的实现。

6、框架业务工具 Comm,Tool,BigPipe

7、daemon队列机制

8、mc

mc的安装

记于2013年11月20日 EOF