轉自 http://blog.congcong.us/archives/283.html
框架的存在主要意義就是提高程序員的開發效率,同時也帶來性能上的一部分損失。
當前開發面向對象已經成為主流,同時為了規范開發使用MVC模式已經成為了一種趨勢,當前市面上的框架非常之多,大部分也是MVC模式,但是相對來說對於PHP性能都一定的損失。
那么有沒有一種框架既能滿足開發效率,又盡可能少的減少性能的損失呢?於是Yaf框架面世。
Yaf是以PHP插件的形式出現,所以少了編譯加載等步驟,加強了性能。提供MVC模式,有一定的路由規則,一定的錯誤處理機制,有一定的觸發器。
同時也伴之有不足之處比如說缺少ORM等形式
Yaf的框架搭建的時候目錄結構:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public
index.php
.htaccess
css
img
js
conf
application.ini
applciation
controllers
Index.php
views
index
index.phtml
modules
library
models
plugins
|
Yaf的啟動
1
2
|
$app
=
new
Yaf_Application(App_PATH.
"/CONF/APPLICATION.INI"
);
$app
->run();
|
配置Yaf的路由規則 開啟URL重寫
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
RewriteEngine On
RewriteCond ${REQUEST_FILENAME} !-f
RewriteRule .* index.php
server{
listen ***;
server_name domain.com
root document_root;
index index.php index.html index.htm
if
(!-e
$request_filename
){
rewrite ^/(.*) /idnex.php/
$1
last;
}
}
|
SAE下的重寫
1
2
3
4
|
name:your_app_name
version:1
handle:
-rewrite:
if
(!
is_dir
() && !
is_file
() && path ~
"^(.*)$"
)
goto
"/index.php"
|
輸出HelloWorld
1
2
3
4
5
6
7
|
<?php
class
IndexController
extends
Yaf_Controller_Abstract{
public
function
indexAction(){
$this
->getView()->assign(
"content"
,
"Hello world"
);
}
}
?>
|
1
2
|
[product]
application.driectory = APP_PATH.
"/application/"
|
創建demo
1
|
yaf_cg sample
|
配置文件 至少一個application.directory
其他可選:
1
2
3
4
5
6
7
8
9
10
11
12
|
application.ext php腳本的擴展名
application.bootstrap Bootstrap路徑
application.library 類庫的絕對目錄地址
application.baseUri 在路由中需要忽略的路徑前綴
applciation.dispatcher.defaultModule 默認的模塊
applciation.dispatcher.throwException 出錯的時候拋出異常
applciation.dispatcher.catchException 使用默認的異常捕獲Controller
application.dispatcher.defaultController 默認控制器
application.dispatcher.defaultAction 默認動作
appcation.view.ext 視圖模板擴展名
appcation.modules 聲明存在的模塊名,注意如果要定義這個值一定要定義Index Module
application.system.* 通過這個屬性,可以修改yaf的runtime configure 比如application.system.lowcase_path,但是請注意只有PHP_INI_ALL的配置項才可以在這里被修改,此選項從2.2.0開始引入
|
自動加載器
Autoloader 目錄映射加載MVC類
非框架MVC類 Yaf支持全局類和自身類的兩種加載方式 支持大小寫敏感和大小寫不敏感兩種方式
全局類和自身類(本地類)
全局類:指有產品之間共享的類,這些類庫的路徑是通過ap.library在php.ini
本地類:產品自身的類庫,這些類庫的路徑是通過在產品的配置文件中,通過ap.library配置的
在yaf中,通過調用Yaf_Loader的regiterLocalNamespace方法,來申明那些類前綴是本地類,即可
類加載規則
下划線分割目錄信息,Yaf按照目錄信息完成自動加載
1
2
|
$loader
= Yaf_Loader::Instance(0);
$loader
->registerLocalNamespace(
array
(
"Foo"
,
"Local"
));
|
Bootstrap 引導程序 提供一個全局配置的入口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
$app
=
new
Yaf_Application(
"conf.ini"
);
$app
->bootstrap()->run();
// _init開頭
//這些方法都接受一個參數:Yaf_Dispatcher $dispatcher
//調用順序按照聲明順序
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"
);
}
}
|
Yaf支持的Hook
routerStartup
routerShutdown
dispatchLoopStartup
preDispatch
posDispatch
dispatchLoopShutdown
自定義插件(可接受兩個參數 Yaf_Request_Abstract 和 Yaf_Response_Abstract)
1
2
3
4
5
|
<?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
){}
}
|
Yaf插件 必須繼承自Yaf_Plugin_Abstract plugins目錄
路由和路由協議
路由組件有兩個部分:路由器(Yaf_Router)和路由協議(Yaf_Route_Abstract).
路由注冊的順序很重要,最后注冊的路由協議,最先嘗試路由,這就有個陷阱,請注意。
Yaf零基礎學習總結1-Yaf框架簡介
從今天開始,給大家講解下yaf框架,講解之前肯定要了解下yaf是個什么東西,當然,從標題我們已經知道yaf是個PHP框架了,也許大家對於PHP框架並不陌生,一般PHP程序員用過的框架至少有一兩個吧,國內用的比較多的有ThinkPHP,YII之類的,用Yaf的還真不多。原因個人感覺有兩個,一個是剛推廣不久,第二個就是門檻高,讓新手無從下手,大多數新手更喜歡用那些使用廣泛,教程文檔多的框架
首先引用yaf的作者對yaf的一個簡單引述:
隨着PHP的發展, PHP框架層出不窮, 但到底用不用PHP框架, 還存在很大的爭論, 反對者認為使用框架會降低性能, 經常舉例的就是Zend Framework. 而支持者則認為,采用框架能提高開發效率, 損失點性能也是值得的.
而這些也正是公司內框架種類繁多的一個原因, 有的項目組為了性能而選擇某些框架, 而另外一些項目組, 則為了更好的封裝選擇了另外的框架
那, 有沒有倆全的辦法呢? 也就是說, 有沒有那么一個框架, 既不會有損性能, 又能提高開發效率呢.
Yaf, 就是為了這個目標而生的.
Yaf有着和Zend Framework相似的API, 相似的理念, 而同時又保持着對Bingo的兼容, 以此來提高開發效率, 規范開發習慣. 本着對性能的追求, Yaf把框架中不易變的部分抽象出來,采用PHP擴展實現(c語言),以此來保證性能.在作者自己做的簡單測試中, Yaf和原生的PHP在同樣功能下, 性能損失小於10%, 而和Zend Framework的對比中, Yaf的性能是Zend Framework的50-60倍.
可以看出,Yaf框架一個最大的優勢就是快,他是用C語言寫的,和原生PHP一樣,速度快,接近原生的PHP,如同作者而言,劍的三層境界:一是手中有劍,心中亦有劍;二是手中無劍,心中有劍;三是手中無劍,心中亦無劍,在和其他用PHP寫的PHP框架來比的話, Yaf就是劍的第二層境界. 框架不在你手中, 而在PHP的"心"中.
官方文檔對Yaf的優點做了以下總結
1. 用C語言開發的PHP框架, 相比原生的PHP, 幾乎不會帶來額外的性能開銷.
2. 所有的框架類, 不需要編譯, 在PHP啟動的時候加載, 並常駐內存.
3. 更短的內存周轉周期, 提高內存利用率, 降低內存占用率.
4. 靈巧的自動加載. 支持全局和局部兩種加載規則, 方便類庫共享.
5. 高性能的視圖引擎.
6. 高度靈活可擴展的框架, 支持自定義視圖引擎, 支持插件, 支持自定義路由等等.
7. 內建多種路由, 可以兼容目前常見的各種路由協議.
8. 強大而又高度靈活的配置文件支持. 並支持緩存配置文件, 避免復雜的配置結構帶來的性能損失.
9. 在框架本身,對危險的操作習慣做了禁止.
10. 更快的執行速度, 更少的內存占用
默認情況下路由器是Yaf_Router 默認路由協議 Yaf_Route_Static 基於Http路由的,他期望一個請求時Http請求並且請求對象是使用yaf_Request_Http
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
//路由器實例
$router
= Yaf_Dispatcher::getInstance()->getRouter();
//路由器協議
$router
->addRoute(
'myRoute'
,
$route
);
在配置文件中定義:
[common]
;自定義路由 順序很重要
routes.regex.type=
"regex"
routes.regex.match =
routes.regex.route.controller = Index
routes.regex.route.action = action
routes.regex.map.1 = name
routes.regex.map.2 = value
;添加一個名為simple的路由協議
routes.simple.type=
"simple"
routes.simple.controller = c
routes.simple.module = m
routes.simple.action = a
;添加一個名為supervar的路由協議
routes.supervar.type =
"supervar"
routes.supervar.varname = r
[product:common]
;product節是Yaf默認關心的節,添加一個名為rewrite的路由協議
routes.rewrite.type =
"rewrite"
routes.rewrite.match =
"/product/:name/:value"
<?php
class
Bootstrap
extends
Yaf_Bootstrap_Abstract{
public
function
_initRoute(Yaf_Dispatcher
$dispatcher
){
$router
= Yaf_Dispatcher::getInstance()->getRouter();
//添加配置中的路由
$router
->addConfig(Yaf_Registry::get(
"config"
)->routes);
}
}
|
//其實路由器也提供給我們不同的方法來得到和設置包含在它內部的信息,一些重要的方法如下:
getCurrentRoute() //在路由結束以后, 獲取起作用的路由協議
getRoute(), getRoutes();//看函數基本意思也就知道.
自定義路由器:申明你的路由協議實現了Yaf_Route_Interface接口即可
異常和錯誤
application.dispatcher.throwException 打開的情況下 會拋異常,否則會觸發錯誤
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
<?php
class
ErrorController
extends
Yaf_Controller_Abstract{
publi
function
errorAction(
$exception
){
//NO1.
assert(
$exception
===
$exception
->getCode());
$this
->getView()->assign(
"code"
,
$exceptioon
->getCode());
$this
->getView()->assign(
"message"
,
$exception
->getMessage());
//NO.2
$exception
=
$this
->getRequest()->getException();
try
{
throw
$exception
;
}
catch
(Yaf_Exception_LoadFailed
$e
) {
//加載失敗
}
catch
(Yaf_Exception
$e
) {
//其他錯誤
}
}
}
|