路由在 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 condition
if ($name != "Bob") {
// Continue to next route
return true;
}
});
Flight::route('/user/*', function(){
// This will get called
});
Flight 被设计成一个可扩展的框架。框架附带了一组默认的方法和组件,但是她允许您映射的自己的方法,注册自己的类,或者覆盖现有的类和方法。
映射你自己的方法,通过 “map
” 方法:
// Map your method
Flight::map('hello', function($name){
echo "hello $name!";
});
// Call your custom method
Flight::hello('Bob');
注册你自己的类,您可以使用 “register
” 方法:
// Register your class
Flight::register('user', 'User');
// Get an instance of your class
$user = Flight::user();
注册方法还允许为你的类构造函数传递参数。因此,当加载你的自定义类,她将预初始化。你可以定义的构造函数参数传递额外的数组。这里有一个加载数据库连接的例子:
// Register class with constructor parameters
Flight::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 constructed
Flight::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 page
include 'errors/404.html';
});
Flight 还允许您替换框架的核心组件 例如可以用你的自定义类替换默认的路由器类
// Register your custom class
Flight::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 method
Flight::map('hello', function($name){
return "Hello, $name!";
});
// Add a before filter
Flight::before('hello', function(&$params, &$output){
// Manipulate the parameter
$params[0] = 'Fred';
});
// Add an after filter
Flight::after('hello', function(&$params, &$output){
// Manipulate the output
$output .= " Have a nice day!";
}
// Invoke the custom method
echo 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 chain
return false;
});
// This will not get called
Flight::before('start', function(&$params, &$output){
echo 'three';
});
注意, “map
” 和 “register
” 等核心方法不能被过滤,因为她们是被直接调用的。
Flight 允许你保存变量,这样就可以在你的应用程序任何地方使用。
// Save your variable
Flight::set('id', 123);
// Elsewhere in your application
$id = Flight::get('id');
查看一个变量是否被你定义:
if (Flight::has('id')) {
// Do something
}
清除你的变量:
// Clears the id variable
Flight::clear('id');
// Clears all variables
Flight::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 library
require './Smarty/libs/Smarty.class.php';
// Register Smarty as the view class
// Also pass a callback function to configure Smarty on load
Flight::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 data
Flight::view()->assign('name', 'Bob');
// Display the template
Flight::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 error
echo $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 - 被请求的 URL
base - 被请求 URL 的父目录
method - 请求方法 (GET, POST, PUT, DELETE)
referrer - 引用的 URL
ip - 客户机的 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;
Flight 提供了内置的 HTTP 缓存。如果缓存条件满足, Flight 将返回一个 HTTP 304 Not Modified
响应。下次客户端请求相同的资源时,她们会提示使用本地缓存版本。
你可以使用 lastModified
传递一个 UNIX 时间戳来设置页面最后修改日期和时间。客户端将继续使用缓存,直到最后修改值发生了改变。
Flight::route('/news', function(){
Flight::lastModified(1234567890);
echo 'This content will be cached.';
});
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();
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();
现在所有的静态方法都可以被作为常规的类方法。
待续.