Yaf 学习日志

Yaf: Yet Another Framework

PHP.net: Yet Another Framework
鸟哥中文文档: Yaf(Yet Another Framework)用户手册

Yaf的优点

天下武功无坚不破,唯快不破

安装/使用

它是通过一个扩展的方式来实现的,我们可以去pecl.php.net去搜索Yaf这个扩展,
我们也可以直接到"http://pecl.php.net/package/yaf"这里进行访问.

对应自己的系统安装即可: 带beta的是测试版, 带stable版的是稳定版.
跟着这个走即可 安装教程

代码生成工具

1
2
3
4
5
6
7
8
// 1.下载源码包
git clone https://github.com/laruence/yaf.git php-yaf

// 2.执行代码生成工具
./php-yaf/tools/cg/yaf_cg yaf-sample

// 3.拷贝生成的代码到自己项目
cd ./php-yaf/tools/cg/output/yaf-sample

快速入门

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/----public   公共目录
| |-------index.php 入口文件
| |-------css 样式目录
| |-------img 图片目录
| |-------js 脚本目录
|
|----conf 配置目录
| |-------app.ini/application.ini 应用程序配置
|
|----app/application 应用程序目录
| |------controllers 控制器目录
| |------views 视图目录
| |------models 模型目录
| |------modules 模块目录
| |------library 类库目录
| |------plugins 插件目录
| |------Bootstrap.php 引导文件
|
|----.htaccess 重写文件 #Apache环境下需要, Nginx不需要

入口文件

  • index.php
1
2
3
4
5
6
7
8
9
10
<?php

//定义应用目录
define("APP_PATH", realpath(dirname(__FILE__).'/../'));

//导入配置文件
$app = new Yaf_Application(APP_PATH . "/conf/app.ini");

//运行程序
echo $app->bootstrap()->run();
  • 改进版入口文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php

// 应用入口文件
date_default_timezone_set("Asia/Shanghai");

if (!defined('__ROOT__')) {
$_root = rtrim(dirname(rtrim($_SERVER['SCRIPT_NAME'], '/')), '/');
define('__ROOT__', (('/' == $_root || '\\' == $_root) ? '' : $_root));
}

//定义应用目录
define("APP_PATH", realpath(dirname(__FILE__).'/../'));

//开发环境 product:线上环境;dev:线下开发环境 test:测试环境
define('APP_ENV', 'dev');

//导入配置文件
$app = new Yaf_Application(APP_PATH . "/conf/app.ini", APP_ENV);

//启动应用
echo $app->bootstrap()->run();

配置文件

  • app.ini

或者application.ini, 基于你的入口文件

1
2
3
4
5
6
7
[common]
;支持直接写PHP中的已定义变量
application.directory = APP_PATH "/app"
application.dispatcher.catchException = true

[dev : common]
;yaf.environ = dev #区分本地、测试和线上的(dev、test、product)

控制器

文件名为Index.php,它的首字母是需要大写的,而且该文件中的控制器的类名必须有Controller后缀,
而且去掉后缀后的部分要和文件名保持一直,而且这个类必须继承自Yaf_Controller_Abstract,而且它里面的所有的动作都必须使用Action后缀。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php
/**
* @name IndexController
* @author Administrator
* @desc 默认控制器
* @see http://www.php.net/manual/en/class.yaf-controller-abstract.php
*/
class IndexController extends Yaf_Controller_Abstract
{
/**
* 默认动作
* Yaf支持直接把Yaf_Request_Abstract::getParam()得到的同名参数作为Action的形参
* 对于如下的例子, 当访问http://yaf.test/index/index/index/name/Administrator 的时候, 你就会发现不同
*/
public function indexAction($name = "caoxl")
{
//1. fetch query
$get = $this->getRequest()->getQuery("get", "default value");

//2. fetch model
$model = new SampleModel();

//3. assign
$this->getView()->assign("content", $model->selectSample());
$this->getView()->assign("name", $name);

//4. render by Yaf, 如果这里返回FALSE, Yaf将不会调用自动视图引擎Render模板
return TRUE;
}
}

控制器须知

  • 每个控制器都需要继承自Yaf_Controller_Abstract这个类,它是所有控制器的父类。
  • 控制器中的动作都需要加Action后缀,比如indexAction,比如readAction等等。
  • 需要特殊说明的是,控制器是默认渲染模板的,我们可以通过如下语句来暂时屏蔽这一功能:
1
Yaf_Dispatcher::getInstance()->disableView();

例如:

1
2
3
4
5
6
7
8
9
10
11
<?php

class StarController extends Yaf_Controller_Abstract
{
// http://yaf.test/star/star
public function starAction()
{
Yaf_Dispatcher::getInstance()->disableView();
echo "当学习成为一种习惯,进步就是一种必然;";
}
}

访问: http://yaf.test/star/star
输出: 当学习成为一种习惯,进步就是一种必然;

  • 还可以在控制器中定义init()方法,它会在每个动作执行之前执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php

class GoController extends Yaf_Controller_Abstract
{
public function init()
{
// 禁止渲染视图
Yaf_Dispatcher::getInstance()->disableView();
echo "来自init()方法<br>";
}

// http://yaf.test/go/show
public function showAction()
{
echo "当学习成为一种习惯,进步就是一种必然;";
}
}
  • 在url中使用”控制器/动作名/参数名1/参数值1/参数名2/参数值2…”的格式来请求即可传递参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php

class ParamsController extends Yaf_Controller_Abstract
{
public function init()
{
// 禁止渲染视图
Yaf_Dispatcher::getInstance()->disableView();
}

// http://yaf.test/params/testParams/name/caoxl/aim/No.1
public function testParamsAction($name, $aim)
{
//输出名字
echo "您的名字是:".$name."<br/>";
//输出目标
echo "您的目标是:".$aim;
}

// http://yaf.test/params/ask/ask/who/answer/me
public function askAction()
{
// 获取参数
$ask = $this->getRequest()->getParam('ask');
$answer = $this->getRequest()->getParam('answer');

echo "您问的问题是:".$ask."<br/>";
echo "您给的答案是:".$answer."<br/>";
}
}

视图

我们在views目录下新建一个index目录,这个目录中对应的是我们的IndexController
该目录下的所有视图文件都是和这个控制器有关系的。然后在index目录中新建一个index.phtml文件,它对应的是indexAction。
需要说明的是,这个后缀默认应该是phtml

1
2
3
<?php

echo $content, " I am ", $name;

视图须知

  • 控制器赋值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

class TestController extends Yaf_Controller_Abstract
{
public function indexAction()
{
$msg = array(
'wife' => '梁超',
'job' => 'PHP'
);
$view = $this->getView();
$view->assign('name', '曹贤亮');
$view->assign('msg', $msg);
}
}
  • 视图渲染

我们在views目录下新建一个test目录,然后在里面创建一个index.phtml文件,然后我们写入如下内容:

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html>
<head>
<title><?php echo $name;?></title>
</head>
<body>
<p>您的姓名是:<?=$name?></p>
<p>您喜欢的人:<?=$msg["wife"]?></p>
<p>您的职位是:<?=$msg["job"]?></p>
</body>
</html>

模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php

/**
* @name SampleModel
* @desc sample数据获取类, 可以访问数据库,文件,其它系统等
* @author caoxl
*/
class SampleModel
{
public function __construct()
{

}

public function selectSample()
{
return "Hello Yaf!";
}

public function insertSample($arr)
{
return true;
}
}

访问: http://yaf.test/index/index
输出: Hello Yaf! I am caoxl

引导文件 Bootstrap.php

我们在app目录下,可以加一个Bootstrap.php文件,该文件会在执行控制器之前执行,而且通常我们在该文件中创建一个Bootstrap类,
继承自Yaf_Bootstrap_Abstract类,而且该类中带有”_init”前缀的方法都会被自动执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?php

/**
* @name Bootstrap
* @author caoxl
* @desc 所有在Bootstrap类中, 以_init开头的方法, 都会被Yaf调用,
* @see http://www.php.net/manual/en/class.yaf-bootstrap-abstract.php
* 这些方法, 都接受一个参数:Yaf_Dispatcher $dispatcher
* 调用的次序, 和申明的次序相同
*/
class Bootstrap extends Yaf_Bootstrap_Abstract
{
public function _initConfig()
{
//禁用视图
//Yaf_Dispatcher::getInstance()->disableView();

//保存配置
$arrConfig = Yaf_Application::app()->getConfig();
Yaf_Registry::set('config', $arrConfig);
}

public function _initPlugin(Yaf_Dispatcher $dispatcher)
{
// 注册插件
$objSamplePlugin = new SamplePlugin();
$dispatcher->registerPlugin($objSamplePlugin);
}

public function _initRoute(Yaf_Dispatcher $dispatcher)
{
// TODO 注册路由协议
}

public function _initView(Yaf_Dispatcher $dispatcher)
{
// TODO 注册View
}
}

不过想让它真正的发挥作用,我们还需要在入口文件中调用bootstrap()方法,即我们的入口文件的代码这么写:

1
2
3
4
5
6
7
8
9
10
<?php

//定义应用目录
define("APP_PATH", realpath(dirname(__FILE__).'/../'));

//导入配置文件
$app = new Yaf_Application(APP_PATH . "/conf/app.ini");

//运行程序
echo $app->bootstrap()->run();

配置

我们必须在Yaf_Application初始化的时候给出配置文件中的配置,其中Yaf的必不可少的配置项只有一个,那就是application.directory,它表示当前应用程序的绝对路径。

1
2
3
4
5
[common]
application.directory = APP_PATH "/app"

[dev : common]
;yaf.environ = dev #区分本地、测试和线上的(dev、test、product)

其实这个配置项也可以没有,至少从框架层面上做到了”零配置”,但是鸟哥认为,如果一个配置项都没有,就显得太寒酸了,于是就加了这么一个配置项。

除了那个必选的配置项之外,我们还有若干的可选配置项,这些配置项我们都可以在conf目录下的app.ini文件中进行定义。

    1. application.ext是php脚本的扩展名,
      它的值默认为php,之所以会有这个配置项,是因为很早很早之前,我们也使用”php3”和”php4”作为后缀名,但是现在的文件我们一般都是使用”php”作为后缀名的,因此这个配置项可以忽略
    1. application.bootstrap是bootstrap文件的绝对路径,也就是我们上面介绍的引导文件,
      它通常是在Yaf_Application实例化之后,我们调用它的bootstrap()方法来进行初始化设置。
    1. application.library是本地类库的绝对路径地址,
      它的默认值为应用程序目录下的library目录,该目录下的类库会被自动加载。
    1. application.baseUri是我们在路由中,需要忽略的路径前缀
      默认值为空,一般不需要设置,Yaf会自动判断。
    1. application.dispatcher.defaultModule是默认的模块名,默认为index。
    1. application.dispatcher.throwException是在出错的时候是否抛出异常,默认值为True,表示抛出异常。
    1. application.dispatcher.catchException是捕获异常用的,
      我们一般使用ErrorController的errorAction()来处理这个异常,我们可以通过$request->getException()来获取异常对象。
    1. application.dispatcher.defaultController是默认的控制器,默认为index。
    1. application.dispatcher.defaultAction是默认的动作,默认为index。
    1. application.view.ext是视图模板扩展名,默认为phtml。
    1. application.modules是存在的模块名,如果我们要定义这个值的话,一定要定义Index模块,默认为Index。

读取配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php

class ConfController extends Yaf_Controller_Abstract
{
public function showAction()
{
$path = APP_PATH . "/conf/test.ini";
$config = new Yaf_Config_ini($path);

//输出信息 这里test ==> test.ini/[test]
echo "您的姓名是:".$config->test->name."<br/>";
echo "您喜欢的是:".$config->test->love;
}
}

其他配置

  • app.ini
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#公共配置
[common]
application.directory = APP_PATH "/app"
application.library.directory = APP_PATH "/library"
application.dispatcher.throwException = TRUE
application.dispatcher.catchException = TRUE

#多个模块,使用逗号分隔
application.modules = Index,Api,Admin
application.view.ext = "phtml"

#日志目录
log_path = APP_PATH "/runtime/logs"

;yaf.environ = dev #区分本地、测试和线上的(dev、test、product)
;开发配置
[dev : common]

;测试配置
[test : common]

;线上配置
[product : common]
  • db.ini
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
[common]
;数据库配置
db.type = "mysql"
db.dsn = ""
db.hostport = "3306"
db.charset = "utf8"

;数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
db.deploy = 0
;数据库读写是否分类 主从式有效
db.rw_separate = false
;读写分离后主服务器数量
db.master_num = 1
;指定从服务器序号
db.slave_no = ""
;是否严格检查字段是否存在
db.fields_strict = true
;数据集返回类型
db.resultset_type = 'array'
;自动写入时间戳字段
db.auto_timestamp = false
;时间字段取出后的默认时间格式
db.datetime_format = 'Y-m-d H:i:s'
db.sql_explain = false

;线上配置
[product : common]
;是否需要进行SQL性能分析
db.sql_explain = false
db.debug = false

;开发配置
[dev : common]
db.hostname = "127.0.0.1"
db.database = "yaf"
db.username = "root"
db.password = "root"
;是否需要进行SQL性能分析
db.sql_explain = true
db.debug = true
db.prefix = "yaf_"
  • rest.ini
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[common]
;CORS 跨域设置 Access-Control-Allow-Origin设置
;['']空,不允许跨站请求
;['*']允许所有域名不限制来源;
;['http://www.xx.com']允许www.xx.com的跨域请求
;允许多个域名用[,]隔开
;开发环境和生产环境可以用不同配置
cors.Access-Control-Allow-Origin = '*';
cors.Access-Control-Allow-Credentials = 'false' ;是否允许跨域使用cookie,'true'允许,false禁止
cors.Access-Control-Allow-Headers = 'x-requested-with,accept,content-type,session-id,token,sessionId,Origin'
cors.Access-Control-Allow-Methods = 'GET,POST,PUT,DELETE,OPTIONS'
cors.Access-Control-Max-Age = 2592000

;REST 响应设置
rest.param = 'id' ;id形默认绑定参数 如 /User/123 =>绑定参数$id值为123
rest.action = 'info' ;默认绑定控制器如 /User/123 =>绑定到 infoAction
rest.none = '_404' ;请求action不存在时调用控制器默认_404Action
rest.status = 'err' ;返回数据的状态码字段
rest.data = 'dat' ;返回数据的数据字段
rest.msg = 'msg' ;返回数据的提示信息
rest.error = -1 ;错误状态码
rest.json = JSON_NUMERIC_CHECK|JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES;

类库加载

默认来说,类库的目录是app目录下的library目录

比如我们在app目录下新建一个library目录,然后我们在改目录中新建一个Tool.php文件,然后我们在里面书写如下代码:

1
2
3
4
5
6
7
8
9
<?php

class Tool
{
public function run()
{
echo "运行Tool类的run方法";
}
}

那么我们在我们的控制器中就可以这么写:

1
2
3
4
5
6
7
8
9
10
<?php

class ToolController extends Yaf_Controller_Abstract
{
public function indexAction()
{
$tool = new Tool();
$tool->run();
}
}

插件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?php

/**
* @name SamplePlugin
* @desc Yaf定义了如下的6个Hook,插件之间的执行顺序是先进先Call
* @see http://www.php.net/manual/en/class.yaf-plugin-abstract.php
* @author caoxl
*/

class SamplePlugin extends Yaf_Plugin_Abstract
{
// 在路由之前触发
public function routerStartup(Yaf_Request_Abstract $request, Yaf_Response_Abstract $response)
{

}

// 路由结束之后触发
public function routerShutdown(Yaf_Request_Abstract $request, Yaf_Response_Abstract $response)
{

}

// 分发循环开始之前被触发
public function dispatchLoopStartup(Yaf_Request_Abstract $request, Yaf_Response_Abstract $response)
{

}

// 分发之前触发
public function preDispatch(Yaf_Request_Abstract $request, Yaf_Response_Abstract $response)
{

}

// 分发结束之后触发
public function postDispatch(Yaf_Request_Abstract $request, Yaf_Response_Abstract $response)
{

}

// 分发循环结束之后触发
public function dispatchLoopShutdown(Yaf_Request_Abstract $request, Yaf_Response_Abstract $response)
{

}
}

数据库

这里可以参考thinkyaf

参考

Powered by Hexo and Hexo-theme-hiker

Copyright © 2017 - 2021 Keep It Simple And Stupid All Rights Reserved.

访客数 : | 访问量 :