快速開始
典型的目錄結(jié)構(gòu)
+ public
|- index.php //入口文件
|- .htaccess //重寫規(guī)則
|+ css
|+ img
|+ js
+ conf
|- application.ini //配置文件
+ application
|+ controllers
|- Index.php //默認(rèn)控制器
|+ views
|+ index //控制器
|- index.phtml //默認(rèn)視圖
|+ modules //其他模塊
|+ library //本地類庫(kù)
|+ models //model目錄
|+ plugins //插件目錄
入口文件
所有請(qǐng)求的入口, 一般都借助于rewrite規(guī)則, 把所有的請(qǐng)求都重定向到這個(gè)入口文件.
經(jīng)典的入口文件public/index.php
<?php
define("APP_PATH", realpath(dirname(__FILE__) . '/../')); /* 指向public的上一級(jí) */
$app = new Yaf_Application(APP_PATH . "/conf/application.ini");
$app->run();
重寫規(guī)則
Apache的Rewrite (httpd.conf)
#.htaccess, 當(dāng)然也可以寫在httpd.conf
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* index.php
Nginx的Rewrite (nginx.conf)
server {
listen ****;
server_name domain.com;
root document_root;
index index.php index.html index.htm;
if (!-e $request_filename) {
rewrite ^/(.*) /index.php/$1 last;
}
}
配置文件
- 配置文件支持繼承, 支持分節(jié). 并對(duì)PHP的常量進(jìn)行支持.
- 在第一個(gè)運(yùn)行的時(shí)候載入配置文件, 把格式化后的內(nèi)容保持在內(nèi)存中. 直到配置文件有了修改, 才會(huì)再次載入.
控制器
- 默認(rèn)的模塊/控制器/動(dòng)作, 都是以Index命名的, 這是可通過配置文件修改的.
- 對(duì)于默認(rèn)模塊, 控制器的目錄是在application目錄下的controllers目錄下, Action的命名規(guī)則是"名字+Action"
默認(rèn)控制器application/controllers/Index.php
<?php
class IndexController extends Yaf_Controller_Abstract {
public function indexAction() {//默認(rèn)Action
$this->getView()->assign("content", "Hello World");
}
}
?>
視圖文件
- Yaf支持簡(jiǎn)單的視圖引擎, 并且支持用戶自定義自己的視圖引擎, 比如Smarty.
- 對(duì)于默認(rèn)模塊, 視圖文件的路徑是在application目錄下的views目錄中以小寫的action名的目錄中.
默認(rèn)Action的視圖application/views/index/index.phtml
<html>
<head>
<title>Hello World</title>
</head>
<body>
<?php echo $content;?>
</body>
</html>
使用代碼生成工具
Yaf提供了代碼生成工具
代碼生成工具的使用
php yaf_cg newapp #newapp 是生成的目錄名
將得到的newapp 目錄, 拷貝到Webserver的documentRoot目錄下
配置文件
php.ini 配置項(xiàng)
php.ini
[yaf]
# 必要配置O茸稀!可以在項(xiàng)目中動(dòng)態(tài)動(dòng)態(tài)調(diào)整想许,來(lái)適應(yīng)不同的生產(chǎn)環(huán)境
yaf.environ = product
yaf.library = NULL
yaf.cache_config = 0
yaf.name_suffix = 1
yaf.name_separator = ""
yaf.forward_limit = 5
yaf.use_namespace = 0
yaf.use_spl_autoload = 0
配置解釋:
yaf.environ
環(huán)境名稱, 當(dāng)用INI作為Yaf的配置文件時(shí), 這個(gè)指明了Yaf將要在INI配置中讀取的節(jié)的名字yaf.library
全局類庫(kù)的目錄路徑yaf.cache_config
是否緩存配置文件(只針對(duì)INI配置文件生效), 打開此選項(xiàng)可在復(fù)雜配置的情況下提高性能yaf.name_suffix
在處理Controller, Action, Plugin, Model的時(shí)候, 類名中關(guān)鍵信息是否是后綴式, 比如UserModel, 而在前綴模式下則是ModelUseryaf.name_separator
在處理Controller, Action, Plugin, Model的時(shí)候, 前綴和名字之間的分隔符, 默認(rèn)為空, 也就是UserPlugin, 加入設(shè)置為"_", 則判斷的依據(jù)就會(huì)變成:"User_Plugin", 這個(gè)主要是為了兼容ST已有的命名規(guī)范yaf.forward_limit
forward最大嵌套深度yaf.use_namespace
開啟的情況下, Yaf將會(huì)使用命名空間方式注冊(cè)自己的類, 比如Yaf_Application將會(huì)變成Yaf\Applicationyaf.use_spl_autoload
開啟的情況下, Yaf在加載不成功的情況下, 會(huì)繼續(xù)讓PHP的自動(dòng)加載函數(shù)加載, 從性能考慮, 除非特殊情況, 否則保持這個(gè)選項(xiàng)關(guān)閉
application.ini配置項(xiàng)
- Yaf_Application初始化時(shí)刻需要給出的必要配置
- Yaf通過在不同的環(huán)境中, 選取不同的配置節(jié), 再結(jié)合配置可繼承, 來(lái)實(shí)現(xiàn)一套配置適應(yīng)多種環(huán)境(線上,測(cè)試,開發(fā)).
必要配置
application.director
應(yīng)用的絕對(duì)目錄路徑
可選的配置
| 名稱 | 值類型 | 默認(rèn)值 | 說明 |
| :-------- |: --------| :------- |:------- |
| application.ext | String | php | PHP腳本的擴(kuò)展名 |
| application.bootstrap | String | Bootstrapplication.php | Bootstrap路徑(絕對(duì)路徑) |
| application.library | String | application.directory + "/library" | 本地(自身)類庫(kù)的絕對(duì)目錄地址 |
| application.baseUri | String | NULL | 在路由中, 需要忽略的路徑前綴, 一般不需要設(shè)置, Yaf會(huì)自動(dòng)判斷. |
| application.dispatcher.defaultModule | String | index | 默認(rèn)的模塊 |
| application.dispatcher.throwException | Bool | True | 在出錯(cuò)的時(shí)候, 是否拋出異常 |
| application.dispatcher.catchException | Bool | False | 是否使用默認(rèn)的異常捕獲Controller, 如果開啟, 在有未捕獲的異常的時(shí)候, 控制權(quán)會(huì)交給ErrorController的errorAction方法, 可以通過$request->getException()獲得此異常對(duì)象 |
| application.dispatcher.defaultController | String | index | 默認(rèn)的控制器 |
| application.dispatcher.defaultAction | String | index | 默認(rèn)的動(dòng)作 |
| application.view.ext | String | phtml | 視圖模板擴(kuò)展名 |
| application.modules | String | Index | 聲明存在的模塊名, 請(qǐng)注意, 如果你要定義這個(gè)值, 一定要定義Index Module |
| application.system.* | String | * | 通過這個(gè)屬性, 可以修改yaf的runtime configure, 比如application.system.lowcase_path, 但是請(qǐng)注意只有PHP_INI_ALL的配置項(xiàng)才可以在這里被修改, 此選項(xiàng)從2.2.0開始引入 |
獲取自定義配置文件:
//獲取所有配置
print_r(Yaf_Application::app()->getConfig());
//獲取單個(gè)配置
print_r(Yaf_Application::app()->getConfig()->redis);
自動(dòng)加載器
Yaf在自啟動(dòng)的時(shí)候, 會(huì)通過SPL注冊(cè)一個(gè)自己的Autoloader, 出于性能的考慮, 對(duì)于框架相關(guān)的MVC類, Yaf Autoloader只以目錄映射的方式嘗試一次.
目錄映射規(guī)則:
| 類型 | 后綴(或者前綴, 可以通過php.ini中ap.name_suffix來(lái)切換) | 映射路徑 |
| :-------- |: --------| :------- |
| 控制器 | Controller | 默認(rèn)模塊下為{項(xiàng)目路徑}/controllers/, 否則為{項(xiàng)目路徑}/modules/{模塊名}/controllers/ |
| 數(shù)據(jù)模型 | Model | {項(xiàng)目路徑}/models/ |
| 插件 | Plugin | {項(xiàng)目路徑}/plugins/ |
全局類和自身類(本地類)
Yaf為了方便在一臺(tái)服務(wù)器上部署的不同產(chǎn)品之間共享公司級(jí)別的共享庫(kù), 支持全局類和本地類兩種加載方式.
- 全局類是指, 所有產(chǎn)品之間共享的類, 這些類庫(kù)的路徑是通過
yaf.library
在php.ini - 本地類是指, 產(chǎn)品自身的類庫(kù)
類的加載規(guī)則
Yaf規(guī)定類名中必須包含路徑信息, 也就是以下劃線"_"分割的目錄信息. Yaf將依照類名中的目錄信息, 完成自動(dòng)加載:
全局類:
一個(gè)映射的例子Zend_Dummy_Foo
//Yaf將在如下路徑尋找類Foo_Dummy_Bar
{類庫(kù)路徑(php.ini中指定的yaf.library)}/Foo/Dummy/Bar.php
本地類:
//申明, 凡是以Foo和Local開頭的類, 都是本地類
$loader = Yaf_Loader::getIgnstance();
$loader->registerLocalNamespace(array("Foo", "Local"));
//Yaf將在如下路徑尋找類Foo_Dummy_Bar
{類庫(kù)路徑(conf/application.ini中指定的yaf.library)}/Foo/Dummy/Bar.php
手動(dòng)導(dǎo)入文件:
Yaf_Loader::import('conf/NetWorkCode.php');
echo NetWorkCode::NETWORK_ERROR;
Bootstrap
簡(jiǎn)介
Bootstrap, 也叫做引導(dǎo)程序. 它是Yaf提供的一個(gè)全局配置的入口, 在Bootstrap中, 你可以做很多全局自定義的工作.
使用Bootstrap
在一個(gè)Yaf_Application被實(shí)例化之后, 運(yùn)行(Yaf_Application::run)之前, 可選的我們可以運(yùn)行Yaf_Application::bootstrap
<?php
$app = new Yaf_Application("conf.ini");
$app
->bootstrap() //可選的調(diào)用
->run();
}
當(dāng)bootstrap被調(diào)用的時(shí)刻, Yaf_Application
就會(huì)默認(rèn)的在APPLICATION_PATH
下, 尋找Bootstrap.php
, 而這個(gè)文件中, 必須定義一個(gè)Bootstrap類, 而這個(gè)類也必須繼承自Yaf_Bootstrap_Abstract
.
實(shí)例化成功之后, 所有在Bootstrap類中定義的, 以_init
開頭的方法, 都會(huì)被依次調(diào)用, 而這些方法都可以接受一個(gè)Yaf_Dispatcher
實(shí)例作為參數(shù).
<?php
/**
* 所有在Bootstrap類中, 以_init開頭的方法, 都會(huì)被Yaf調(diào)用,
* 這些方法, 都接受一個(gè)參數(shù):Yaf_Dispatcher $dispatcher
* 調(diào)用的次序, 和申明的次序相同
*/
class Bootstrap extends Yaf_Bootstrap_Abstract{
public function _initConfig() {
$config = Yaf_Application::app()->getConfig();
Yaf_Registry::set("config", $config);
}
public function _initDefaultName(Yaf_Dispatcher $dispatcher) {
$dispatcher->setDefaultModule("Index")->setDefaultController("Index")->setDefaultAction("index");
}
}
插件
簡(jiǎn)介
Yaf支持用戶定義插件來(lái)擴(kuò)展Yaf的功能. 它們都必須繼承自Yaf_Plugin_Abstract. 插件要發(fā)揮功效, 也必須現(xiàn)實(shí)的在Yaf中進(jìn)行注冊(cè), 然后在適當(dāng)?shù)膶?shí)際, Yaf就會(huì)調(diào)用它.
Yaf支持的Hook
| 觸發(fā)順序 | 名稱 | 觸發(fā)時(shí)機(jī) | 說明 |
| :-------- |: --------| :------- |:------- |
| 1 | routerStartup | 在路由之前觸發(fā) | 這個(gè)是7個(gè)事件中, 最早的一個(gè). 但是一些全局自定的工作, 還是應(yīng)該放在Bootstrap中去完成 |
| 2 | routerShutdown | 路由結(jié)束之后觸發(fā) | 此時(shí)路由一定正確完成, 否則這個(gè)事件不會(huì)觸發(fā) |
| 3 | dispatchLoopStartup | 分發(fā)循環(huán)開始之前被觸發(fā) |
| 4 | preDispatch | 分發(fā)之前觸發(fā) | 如果在一個(gè)請(qǐng)求處理過程中, 發(fā)生了forward, 則這個(gè)事件會(huì)被觸發(fā)多次 |
| 5 | postDispatch | 分發(fā)結(jié)束之后觸發(fā) | 此時(shí)動(dòng)作已經(jīng)執(zhí)行結(jié)束, 視圖也已經(jīng)渲染完成. 和preDispatch類似, 此事件也可能觸發(fā)多次 |
| 6 | dispatchLoopShutdown | 分發(fā)循環(huán)結(jié)束之后觸發(fā) | 此時(shí)表示所有的業(yè)務(wù)邏輯都已經(jīng)運(yùn)行完成, 但是響應(yīng)還沒有發(fā)送 |
定義插件
- 繼承自Yaf_Plugin_Abstract
- 需要在插件類中定義和上面事件同名的方法
- 方法就會(huì)在該事件觸發(fā)的時(shí)候被調(diào)用
- 插件方法, 可以接受倆個(gè)參數(shù), Yaf_Request_Abstract實(shí)例和Yaf_Response_Abstract實(shí)例
<?php
class UserPlugin 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) {
}
}
注冊(cè)插件
向Yaf_Dispatcher
注冊(cè)插件, 一般的插件注冊(cè)都會(huì)放在Bootstrap
中進(jìn)行
<?php
class Bootstrap extends Yaf_Bootstrap_Abstract{
public function _initPlugin(Yaf_Dispatcher $dispatcher) {
$user = new UserPlugin();
$dispatcher->registerPlugin($user);
}
}
插件目錄
放置在APPLICATION_PATH
下的plugins
目錄, 這樣在自動(dòng)加載的時(shí)候, 加載器通過類名, 發(fā)現(xiàn)這是個(gè)插件類
路由和路由協(xié)議
概述
路由器主要負(fù)責(zé)解析一個(gè)請(qǐng)求并且決定什么module剥汤、controller、action被請(qǐng)求;它同時(shí)也定義了一種方法來(lái)實(shí)現(xiàn)用戶自定義路由骚秦,這也使得它成為最重要的一個(gè)MVC組組件.
路由組件有兩個(gè)部分:路由器(Yaf_Router)和路由協(xié)議(Yaf_Route_Abstract).
默認(rèn)情況下,我們的路由器是Yaf_Router, 而默認(rèn)使用的路由協(xié)議是Yaf_Route_Static,是基于HTTP路由的
路由類別
Yaf_Route_Simple
Yaf_Route_Supervar
Yaf_Route_Static
Yaf_Route_Map
Yaf_Route_Rewrite
Yaf_Route_Regex
默認(rèn)路由協(xié)議
默認(rèn)的路由協(xié)議Yaf_Route_Static
, 就是分析請(qǐng)求中的request_uri
, 在去除掉base_uri以后, 獲取到真正的負(fù)載路由信息的request_uri片段, 具體的策略是, 根據(jù)"/"對(duì)request_uri分段, 依次得到Module,Controller,Action,
在得到Module以后, 還需要根據(jù)Yaf_Application::$modules
來(lái)判斷Module是否是合法的Module, 如果不是, 則認(rèn)為Module并沒有體現(xiàn)在request_uri中, 而把原Module當(dāng)做Controller, 原Controller當(dāng)做Action:
工作中默認(rèn)的即可滿足需求她倘,如果有需要可以自己定制
具體參考:http://www.laruence.com/manual/yaf.routes.html
簡(jiǎn)單路由
/*
* http://yaf.test.com/?m=order&c=orderinfo&a=show
*/
// $router=$dispatcher->getRouter();
// $route = new Yaf_Route_Simple("m", "c", "a");
// $router->addRoute("name", $route);