yaf 基础

快速开始

典型的目录结构

+ public
  |- index.php //入口文件
  |- .htaccess //重写规则    
  |+ css
  |+ img
  |+ js
+ conf
  |- application.ini //配置文件   
+ application
  |+ controllers
     |- Index.php //默认控制器
  |+ views    
     |+ index   //控制器
        |- index.phtml //默认视图
  |+ modules //其他模块
  |+ library //本地类库
  |+ models  //model目录
  |+ plugins //插件目录

入口文件

所有请求的入口, 一般都借助于rewrite规则, 把所有的请求都重定向到这个入口文件.

经典的入口文件public/index.php

<?php
define("APP_PATH",  realpath(dirname(__FILE__) . '/../')); /* 指向public的上一级 */
$app  = new Yaf_Application(APP_PATH . "/conf/application.ini");
$app->run();

重写规则

Apache的Rewrite (httpd.conf)

#.htaccess, 当然也可以写在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;
  }
}

配置文件

  • 配置文件支持继承, 支持分节. 并对PHP的常量进行支持.
  • 在第一个运行的时候载入配置文件, 把格式化后的内容保持在内存中. 直到配置文件有了修改, 才会再次载入.

控制器

  • 默认的模块/控制器/动作, 都是以Index命名的, 这是可通过配置文件修改的.
  • 对于默认模块, 控制器的目录是在application目录下的controllers目录下, Action的命名规则是"名字+Action"

默认控制器application/controllers/Index.php

<?php
class IndexController extends Yaf_Controller_Abstract {
   public function indexAction() {//默认Action
       $this->getView()->assign("content", "Hello World");
   }
}
?>

视图文件

  • Yaf支持简单的视图引擎, 并且支持用户自定义自己的视图引擎, 比如Smarty.
  • 对于默认模块, 视图文件的路径是在application目录下的views目录中以小写的action名的目录中.

默认Action的视图application/views/index/index.phtml

<html>
 <head>
   <title>Hello World</title>
 </head>
 <body>
  <?php echo $content;?>
 </body>
</html>

使用代码生成工具

Yaf提供了代码生成工具

github地址

代码生成工具的使用

php yaf_cg newapp #newapp 是生成的目录名

将得到的newapp 目录, 拷贝到Webserver的documentRoot目录下


配置文件

php.ini 配置项

php.ini

[yaf]
# 必要配置!!可以在项目中动态动态调整,来适应不同的生产环境
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 环境名称, 当用INI作为Yaf的配置文件时, 这个指明了Yaf将要在INI配置中读取的节的名字

  • yaf.library 全局类库的目录路径

  • yaf.cache_config 是否缓存配置文件(只针对INI配置文件生效), 打开此选项可在复杂配置的情况下提高性能

  • yaf.name_suffix 在处理Controller, Action, Plugin, Model的时候, 类名中关键信息是否是后缀式, 比如UserModel, 而在前缀模式下则是ModelUser

  • yaf.name_separator 在处理Controller, Action, Plugin, Model的时候, 前缀和名字之间的分隔符, 默认为空, 也就是UserPlugin, 加入设置为"_", 则判断的依据就会变成:"User_Plugin", 这个主要是为了兼容ST已有的命名规范

  • yaf.forward_limit forward最大嵌套深度

  • yaf.use_namespace 开启的情况下, Yaf将会使用命名空间方式注册自己的类, 比如Yaf_Application将会变成Yaf\Application

  • yaf.use_spl_autoload 开启的情况下, Yaf在加载不成功的情况下, 会继续让PHP的自动加载函数加载, 从性能考虑, 除非特殊情况, 否则保持这个选项关闭

application.ini配置项

  • Yaf_Application初始化时刻需要给出的必要配置
  • Yaf通过在不同的环境中, 选取不同的配置节, 再结合配置可继承, 来实现一套配置适应多种环境(线上,测试,开发).

必要配置

application.director 应用的绝对目录路径

可选的配置

| 名称 | 值类型 | 默认值 | 说明 |
| :-------- |: --------| :------- |:------- |
| application.ext | String | php | PHP脚本的扩展名 |
| application.bootstrap | String | Bootstrapplication.php | Bootstrap路径(绝对路径) |
| application.library | String | application.directory + "/library" | 本地(自身)类库的绝对目录地址 |
| application.baseUri | String | NULL | 在路由中, 需要忽略的路径前缀, 一般不需要设置, Yaf会自动判断. |
| application.dispatcher.defaultModule | String | index | 默认的模块 |
| application.dispatcher.throwException | Bool | True | 在出错的时候, 是否抛出异常 |
| application.dispatcher.catchException | Bool | False | 是否使用默认的异常捕获Controller, 如果开启, 在有未捕获的异常的时候, 控制权会交给ErrorController的errorAction方法, 可以通过$request->getException()获得此异常对象 |
| application.dispatcher.defaultController | String | index | 默认的控制器 |
| application.dispatcher.defaultAction | String | index | 默认的动作 |
| application.view.ext | String | phtml | 视图模板扩展名 |
| application.modules | String | Index | 声明存在的模块名, 请注意, 如果你要定义这个值, 一定要定义Index Module |
| application.system.* | String | * | 通过这个属性, 可以修改yaf的runtime configure, 比如application.system.lowcase_path, 但是请注意只有PHP_INI_ALL的配置项才可以在这里被修改, 此选项从2.2.0开始引入 |

获取自定义配置文件:

//获取所有配置
print_r(Yaf_Application::app()->getConfig());
//获取单个配置
print_r(Yaf_Application::app()->getConfig()->redis);

自动加载器

Yaf在自启动的时候, 会通过SPL注册一个自己的Autoloader, 出于性能的考虑, 对于框架相关的MVC类, Yaf Autoloader只以目录映射的方式尝试一次.

目录映射规则:

| 类型 | 后缀(或者前缀, 可以通过php.ini中ap.name_suffix来切换) | 映射路径 |
| :-------- |: --------| :------- |
| 控制器 | Controller | 默认模块下为{项目路径}/controllers/, 否则为{项目路径}/modules/{模块名}/controllers/ |
| 数据模型 | Model | {项目路径}/models/ |
| 插件 | Plugin | {项目路径}/plugins/ |

全局类和自身类(本地类)

Yaf为了方便在一台服务器上部署的不同产品之间共享公司级别的共享库, 支持全局类和本地类两种加载方式.

  • 全局类是指, 所有产品之间共享的类, 这些类库的路径是通过yaf.library在php.ini
  • 本地类是指, 产品自身的类库

类的加载规则

Yaf规定类名中必须包含路径信息, 也就是以下划线"_"分割的目录信息. Yaf将依照类名中的目录信息, 完成自动加载:

全局类:

一个映射的例子Zend_Dummy_Foo

 //Yaf将在如下路径寻找类Foo_Dummy_Bar
 {类库路径(php.ini中指定的yaf.library)}/Foo/Dummy/Bar.php

本地类:

  //申明, 凡是以Foo和Local开头的类, 都是本地类
 $loader = Yaf_Loader::getIgnstance();
 $loader->registerLocalNamespace(array("Foo", "Local"));
 //Yaf将在如下路径寻找类Foo_Dummy_Bar
 {类库路径(conf/application.ini中指定的yaf.library)}/Foo/Dummy/Bar.php

手动导入文件:

Yaf_Loader::import('conf/NetWorkCode.php');
echo NetWorkCode::NETWORK_ERROR;

Bootstrap

简介

Bootstrap, 也叫做引导程序. 它是Yaf提供的一个全局配置的入口, 在Bootstrap中, 你可以做很多全局自定义的工作.

使用Bootstrap

在一个Yaf_Application被实例化之后, 运行(Yaf_Application::run)之前, 可选的我们可以运行Yaf_Application::bootstrap

<?php
$app = new Yaf_Application("conf.ini");
$app
 ->bootstrap() //可选的调用
 ->run();
}

当bootstrap被调用的时刻, Yaf_Application就会默认的在APPLICATION_PATH下, 寻找Bootstrap.php, 而这个文件中, 必须定义一个Bootstrap类, 而这个类也必须继承自Yaf_Bootstrap_Abstract.

实例化成功之后, 所有在Bootstrap类中定义的, 以_init开头的方法, 都会被依次调用, 而这些方法都可以接受一个Yaf_Dispatcher实例作为参数.

<?php

/**
 * 所有在Bootstrap类中, 以_init开头的方法, 都会被Yaf调用,
 * 这些方法, 都接受一个参数: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支持用户定义插件来扩展Yaf的功能. 它们都必须继承自Yaf_Plugin_Abstract. 插件要发挥功效, 也必须现实的在Yaf中进行注册, 然后在适当的实际, Yaf就会调用它.

Yaf支持的Hook

| 触发顺序 | 名称 | 触发时机 | 说明 |
| :-------- |: --------| :------- |:------- |
| 1 | routerStartup | 在路由之前触发 | 这个是7个事件中, 最早的一个. 但是一些全局自定的工作, 还是应该放在Bootstrap中去完成 |
| 2 | routerShutdown | 路由结束之后触发 | 此时路由一定正确完成, 否则这个事件不会触发 |
| 3 | dispatchLoopStartup | 分发循环开始之前被触发 |
| 4 | preDispatch | 分发之前触发 | 如果在一个请求处理过程中, 发生了forward, 则这个事件会被触发多次 |
| 5 | postDispatch | 分发结束之后触发 | 此时动作已经执行结束, 视图也已经渲染完成. 和preDispatch类似, 此事件也可能触发多次 |
| 6 | dispatchLoopShutdown | 分发循环结束之后触发 | 此时表示所有的业务逻辑都已经运行完成, 但是响应还没有发送 |

定义插件

  • 继承自Yaf_Plugin_Abstract
  • 需要在插件类中定义和上面事件同名的方法
  • 方法就会在该事件触发的时候被调用
  • 插件方法, 可以接受俩个参数, Yaf_Request_Abstract实例和Yaf_Response_Abstract实例
    <?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_Dispatcher注册插件, 一般的插件注册都会放在Bootstrap中进行

<?php
class Bootstrap extends Yaf_Bootstrap_Abstract{

        public function _initPlugin(Yaf_Dispatcher $dispatcher) {
            $user = new UserPlugin();
            $dispatcher->registerPlugin($user);
        }
}

插件目录

放置在APPLICATION_PATH下的plugins目录, 这样在自动加载的时候, 加载器通过类名, 发现这是个插件类

路由和路由协议

概述

路由器主要负责解析一个请求并且决定什么module、controller、action被请求;它同时也定义了一种方法来实现用户自定义路由,这也使得它成为最重要的一个MVC组组件.

路由组件有两个部分:路由器(Yaf_Router)和路由协议(Yaf_Route_Abstract).

默认情况下,我们的路由器是Yaf_Router, 而默认使用的路由协议是Yaf_Route_Static,是基于HTTP路由的

路由类别

Yaf_Route_Simple
Yaf_Route_Supervar
Yaf_Route_Static
Yaf_Route_Map
Yaf_Route_Rewrite
Yaf_Route_Regex

默认路由协议

默认的路由协议Yaf_Route_Static, 就是分析请求中的request_uri, 在去除掉base_uri以后, 获取到真正的负载路由信息的request_uri片段, 具体的策略是, 根据"/"对request_uri分段, 依次得到Module,Controller,Action, 在得到Module以后, 还需要根据Yaf_Application::$modules来判断Module是否是合法的Module, 如果不是, 则认为Module并没有体现在request_uri中, 而把原Module当做Controller, 原Controller当做Action:

工作中默认的即可满足需求,如果有需要可以自己定制

具体参考:http://www.laruence.com/manual/yaf.routes.html

简单路由

/*
    * 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);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,529评论 5 475
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,015评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,409评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,385评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,387评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,466评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,880评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,528评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,727评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,528评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,602评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,302评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,873评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,890评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,132评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,777评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,310评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,579评论 18 139
  • 介绍 Yaf框架是一个c语言编写的PHP框架,是一个以PHP扩展形式提供的PHP开发框架,相比于一般的PHP框架,...
    简单方式阅读 18,650评论 1 44
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,361评论 25 707
  • 蚂蚁冬眠的季节 你的思念像一片片落叶 风将你的爱吹去千里之外 南方的冬天更加湿冷 请你多添些衣裳 多日不见 是否还...
    Derek_Kun阅读 841评论 1 5
  • 林俊杰-曹操 在中国我们从小就被反复地告知“第一印象很重要”。因此,我们在和他人第一次见面时,必然得好好地收拾打扮...
    一缕鱼魂阅读 330评论 0 1