用户指南
路由
路由在 Flight 中是通过与一个回调函数匹配的URL模式。
Flight::route('/', function(){echo 'hello world!';});
可调用的回调可以是任何对象。所以你可以使用常规的功能:
function hello(){echo 'hello world!';}Flight::route('/', 'hello');
或者是一个类方法:
class Greeting {public static function hello() {echo 'hello world!';}}Flight::route('/', array('Greeting','hello'));
路由的匹配根据顺序定义。第一个匹配的路由请求将被调用。
路由方法
默认情况下,路由模式匹配的方法允许所有请求。你可以对特定的方法将一个标识符放在URL前面。
Flight::route('GET /', function(){echo 'I received a GET request.';});Flight::route('POST /', function(){echo 'I received a POST request.';});
您还可以将多个方法映射到一个回调,使用一个 “|
” 分隔符:
Flight::route('GET|POST /', function(){echo 'I received either a GET or a POST request.';});
正则表达式
你可以在路由中使用正则表达式:
Flight::route('/user/[0-9]+', function(){// This will match /user/1234});
命名参数
你可以指定命名参数路由,她将被传递到你的回调函数。
Flight::route('/@name/@id', function($name, $id){echo "hello, $name ($id)!";});
你还可以使用包含正则表达式的命名参数,通过使用 “:
” 分隔符:
Flight::route('/@name/@id:[0-9]{3}', function($name, $id){// This will match /bob/123// But will not match /bob/12345});
可选参数
您可以指定可选的命名参数,她被包在匹配的括号中。
Flight::route('/blog(/@year(/@month(/@day)))', function($year, $month, $day){// This will match the following URLS:// /blog/2012/12/10// /blog/2012/12// /blog/2012// /blog});
任何可选参数没有匹配将被传递NULL。
通配符
如果你想在单独URL部分匹配多个片段的路由。可以使用 “*
” 通配符。
Flight::route('/blog/*', function(){// This will match /blog/2000/02/01});
所有的请求路由到一个回调,你可以写点东西:
Flight::route('*', function(){// Do something});
通过
您可以通过在回调函数通过返回 true
执行到下一个匹配的路由。
Flight::route('/user/@name', function($name){// Check some conditionif ($name != "Bob") {// Continue to next routereturn true;}});Flight::route('/user/*', function(){// This will get called});
扩展
Flight 被设计成一个可扩展的框架。框架附带了一组默认的方法和组件,但是她允许您映射的自己的方法,注册自己的类,或者覆盖现有的类和方法。
映射方法
映射你自己的方法,通过 “map
” 方法:
// Map your methodFlight::map('hello', function($name){echo "hello $name!";});// Call your custom methodFlight::hello('Bob');
注册类
注册你自己的类,您可以使用 “register
” 方法:
// Register your classFlight::register('user', 'User');// Get an instance of your class$user = Flight::user();
注册方法还允许为你的类构造函数传递参数。因此,当加载你的自定义类,她将预初始化。你可以定义的构造函数参数传递额外的数组。这里有一个加载数据库连接的例子:
// Register class with constructor parametersFlight::register('db', 'PDO', array('mysql:host=localhost;dnbname=test','user','pass'));// Get an instance of your class// This will create an object with the defined parameters//// new PDO('mysql:host=localhost;dnbname=test','user','pass');//$db = Flight::db();
如果你加了一个额外的回调参数,她将在类构建后立即执行。这允许你在新对象执行任何程序设置。回调函数接受一个参数,新对象的一个实例。
// The callback will be passed the object that was constructedFlight::register('db', 'PDO', array('mysql:host=localhost;dnbname=test','user','pass'), function($db){$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);});
默认情况下,每次你加载你的类都会得到一个共享实例。要得到一个新的实例,简单地通过 “false
” 作为参数:
// Shared instance of the class$shared = Flight::db();// New instance of the class$new = Flight::db(false);
请记住,映射方法在注册类时有优先选择。如果你的声明都使用相同的名称,只有映射到的方法被调用。
覆盖
Flight 允许你覆盖默认的功能来满足自己的需求,而不需要修改任何代码。
例如, 当 Flight 没有匹配到 URL 的路由, 她会调用 “notFound
” 方法发送一个通用的 “HTTP 404
” 响应。 您可以覆盖此行为通过使用 “map
” 方法:
Flight::map('notFound', function(){// Display custom 404 pageinclude 'errors/404.html';});
Flight 还允许您替换框架的核心组件 例如可以用你的自定义类替换默认的路由器类
// Register your custom classFlight::register('router', 'MyRouter');// When Flight loads the Router instance, it will load your class$myrouter = Flight::router();
Framework 的 “map
” 和 “register
” 方法不能被覆盖。如果你这样做,会得到一个错误。
过滤
Flight 允许你在调用之前和之后使用过滤方法。你需要记住它没有预定义的钩子。您可以过滤任何默认的框架方法以及任何你自定义的映射方法。
一个过滤器函数如下所示:
function(&$params, &$output) {// Filter code}
你可以使用传入的变量操纵输入或输出参数。
你可以在运行之前加一个过滤,像这样:
Flight::before('start', function(&$params, &$output){// Do something});
你可以在运行之后加一个过滤,像这样:
Flight::after('start', function(&$params, &$output){// Do something});
你可以添加多个过滤器来实现你想要的任何方法。她会按照声明的顺序执行。
这是一个过滤的例子:
// Map a custom methodFlight::map('hello', function($name){return "Hello, $name!";});// Add a before filterFlight::before('hello', function(&$params, &$output){// Manipulate the parameter$params[0] = 'Fred';});// Add an after filterFlight::after('hello', function(&$params, &$output){// Manipulate the output$output .= " Have a nice day!";}// Invoke the custom methodecho Flight::hello('Bob');
她将这样显示:
Hello Fred! Have a nice day!
如果定义了多个过滤器,你可以在任何地方通过返回 “false
” 来打破过滤功能:
Flight::before('start', function(&$params, &$output){echo 'one';});Flight::before('start', function(&$params, &$output){echo 'two';// This will end the chainreturn false;});// This will not get calledFlight::before('start', function(&$params, &$output){echo 'three';});
注意, “map
” 和 “register
” 等核心方法不能被过滤,因为她们是被直接调用的。
变量
Flight 允许你保存变量,这样就可以在你的应用程序任何地方使用。
// Save your variableFlight::set('id', 123);// Elsewhere in your application$id = Flight::get('id');
查看一个变量是否被你定义:
if (Flight::has('id')) {// Do something}
清除你的变量:
// Clears the id variableFlight::clear('id');// Clears all variablesFlight::clear();
Flight 还可以修改配置变量
Flight::set('flight.log_errors', true);
视图
默认情况下 Flight 提供了一些基本的模板功能。调用 “render
” 方法来显示一个视图模板并可传递一些数据:
Flight::render('hello.php', array('name' => 'Bob'));
你传入的模板数据将作为一个局部变量自动注入到引用的模板。模板文件是简单的 .php 文件。如果模板文件 “hello.php
” 是这样的:
Hello, '<?php echo $name; ?>'!
她将输出:
Hello, Bob!
你也可以用 set 方法手动设置视图变量:
Flight::view()->set('name', 'Bob');
name
变量可以用在你的所有视图中。所以你可以更简单的写成这样:
Flight::render('hello');
注意,当在 render 方法中指定模板的名称时, 你可以不用写 .php
文件后缀。
默认情况下 Flight 将寻找一个 “views
” 的文件目录。你可以通过以下配置设置一个替代的模板路径:
Flight::set('flight.views.path', '/path/to/views');
布局
网站有一个常见的布局模板文件用来交换内容。在呈现一个布局时,你可以传递一个可选参数到 “render
” 方法。
Flight::render('header', array('heading' => 'Hello'), 'header_content');Flight::render('body', array('body' => 'World'), 'body_content');
你的视图将被保存在名为 “header_content
” 和 “body_content
” 的变量中,你可以在布局中这样做:
Flight::render('layout', array('title' => 'Home Page'));
如果模板文件像这样:
header.php
:
<h1><?php echo $heading; ?></h1>
body.php
:
<div><?php echo $body; ?></div>
layout.php
:
<html><head><title><?php echo $title; ?></title></head><body><?php echo $header_content; ?><?php echo $body_content; ?></body></html>
她将输出:
<html><head><title>Home Page</title></head><body><h1>Hello</h1><div>World</div></body></html>
自定义视图
Flight 允许你替换默认的视图引擎,只需注册自己的视图类。下面是如何使用 Smarty 模板引擎到你的视图:
// Load Smarty libraryrequire './Smarty/libs/Smarty.class.php';// Register Smarty as the view class// Also pass a callback function to configure Smarty on loadFlight::register('view', 'Smarty', array(), function($smarty){$smarty->template_dir = './templates/';$smarty->compile_dir = './templates_c/';$smarty->config_dir = './config/';$smarty->cache_dir = './cache/';});// Assign template dataFlight::view()->assign('name', 'Bob');// Display the templateFlight::view()->display('hello.tpl');
出于完整性的考虑,你也应该覆盖 Flight 的默认渲染方法:
Flight::map('render', function($template, $data){Flight::view()->assign($data);Flight::view()->display($template);});
错误处理
错误和异常
所有的错误和异常都 Flight 传递到 “error
” 方法中。 默认行为是发送一个通用 “HTTP 500 Internal Server Error
” 响应,来显示一些简单的错误信息。
你可以根据自己的需求覆盖此行为:
Flight::map('error', function(Exception $ex){// Handle errorecho $ex->getTraceAsString();});
默认情况下,错误没有被记录到 web server。您可以通过改变配置启用她:
Flight::set('flight.log_errors', true);
没有找到
当一个 URL 没有被找到, Flight 将调用 notFound
方法。默认行为是发送一个 HTTP 404 Not Found
响应,来显示一些简单的错误信息。
你可以根据自己的需求覆盖此行为:
Flight::map('notFound', function(){// Handle not found});
重定向
您可以传递一个新的 URL 通过 “redirect
” 方法重定向。:
Flight::redirect('/new/location');
默认情况下 Flight 发送一个 HTTP 303 状态码。你可以自定义一个代码:
Flight::redirect('/new/location', 401);
请求
Flight 封装 HTTP 请求到一个对象, 你可以通过这样访问:
$request = Flight::request();
请求对象提供了以下属性:
url - 被请求的 URLbase - 被请求 URL 的父目录method - 请求方法 (GET, POST, PUT, DELETE)referrer - 引用的 URLip - 客户机的 IP 地址ajax - 是不是一个 AJAX 请求scheme - 服务器协议 (http, https)user_agent - 浏览器的信息body - 请求主体的原始数据type - 内容类型length - 内容长度query - 查询字符串参数data - Post 参数cookies - Cookie 参数files - 上传的文件secure - 连接是否安全accept - HTTP 接受参数proxy_ip - 代理客户机的 IP 地址
你可以通过数组或对象访问 query
,data
,cookies
和 files
属性。
因此,要查询一个参数, 你可以这样:
$id = Flight::request()->query['id'];
或者这样:
$id = Flight::request()->query->id;
HTTP 缓存
Flight 提供了内置的 HTTP 缓存。如果缓存条件满足, Flight 将返回一个 HTTP 304 Not Modified
响应。下次客户端请求相同的资源时,她们会提示使用本地缓存版本。
最后修改
你可以使用 lastModified
传递一个 UNIX 时间戳来设置页面最后修改日期和时间。客户端将继续使用缓存,直到最后修改值发生了改变。
Flight::route('/news', function(){Flight::lastModified(1234567890);echo 'This content will be cached.';});
ETag
ETag
缓存同 Last-Modified
类似,除了你可以指定任何你想要的id资源:
Flight::route('/news', function(){Flight::etag('my-unique-id');echo 'This content will be cached.';});
记住,使用 lastModified
或 etag
时都将设置并检查缓存值。如果缓存值于请求之间是相同的, Flight 将立即发送一个 HTTP 304
响应并停止处理。
停止
你可以在任何时候调用 halt
方法停止框架:
Flight::halt();
你还可以指定一个可选的 HTTP
状态代码和信息:
Flight::halt(200, 'Be right back...');
调用 halt
方法将丢弃任何响应内容。如果你想要停止框架并输出当前的响应,使用 stop
方法:
Flight::stop();
JSON
Flight 支持发送 JSON 和 JSONP 响应。 你可以通过 json 方法传递一些JSON编码的数据:
Flight::json(array('id' => 123));
你可以使用 jsonp
方法用于 JSONP 请求。你可以通过传递查询参数名来定义你正在使用的回调函数:
Flight::jsonp(array('id' => 123), 'q');
所以,当制造一个GET请求,使用 ?q=my_func
,你会得到这样的输出:
my_func({"id":123});
如果你不传递查询参数名将默认使用 jsonp
。
配置
您可以自定义 Flight 的某些行为,通过使用 set
方法。
Flight::set('flight.log_errors', true);
下面是一个所有可用配置的列表。
flight.base_url - 覆盖 base url 请求。 (默认: null)flight.handle_errors - 允许 Flight 处理所有内部错误。 (默认: true)flight.log_errors - 将错误日志记录到 web server 的错误日志文件。 (默认: false)flight.views.path - 包含视图模板文件的目录 (默认: ./views)
框架方法
Flight 被设计为易于使用和理解。下面是框架的全套方法。它包含的核心方法,常规的静态方法,和可扩展的方法,可以过滤或覆盖。
核心方法
Flight::map($name, $callback) // 创建一个自定义框架的方法。Flight::register($name, $class, [$params], [$callback]) // 注册一个类的框架方法。Flight::before($name, $callback) // 在一个框架方法之前添加一个过滤器。Flight::after($name, $callback) // 在一个框架方法之后添加一个过滤器。Flight::path($path) // 添加了一个半自动的类路径。Flight::get($key) // 得到一个变量。Flight::set($key, $value) // 设置一个变量。Flight::has($key) // 检查一个变量是否设置。Flight::clear([$key]) // 清除一个变量。
可扩展的方法
Flight::start() // 开始框架Flight::stop() // 停止该框架并发送一个响应。Flight::halt([$code], [$message]) // 停止该框架并带一个可选的状态代码和消息。Flight::route($pattern, $callback) // 映射一个 URL 模式到回调。Flight::redirect($url, [$code]) // 重定向到另一个URL。Flight::render($file, [$data], [$key]) // 呈现一个模板文件。Flight::error($exception) // 发送一个 HTTP 500 响应。Flight::notFound() // 发送一个 HTTP 404 响应。Flight::etag($id, [$type]) // 执行 ETag HTTP 缓存。Flight::lastModified($time) // 执行最后更改的 HTTP 缓存。Flight::json($data, [$code], [$encode]) // 发送一个 JSON 响应。Flight::jsonp($data, [$param], [$code], [$encode]) // 发送一个 JSONP 响应。
任何被 map
和 register
的自定义方法都可以被过滤。
框架实例
Flight 并不是作为一个全局静态类运行,您可以选择作为一个对象实例运行它。
require 'flight/autoload.php';use flight\Engine;$app = new Engine();$app->route('/', function(){echo 'hello world!';});$app->start();
现在所有的静态方法都可以被作为常规的类方法。
待续.