Flight是一个快速,简易,可扩展的PHP框架。Flight能使你快速和轻松地建立RESTful Web应用。php
require 'flight/Flight.php'; Flight::route('/', function(){ echo 'hello world!'; }); Flight::start();
Flight须要PHP 5.3
或更高版本。html
Flight is released under the MIT license.mysql
1.框架下载git
若是你在使用Composer,你能够运行以下命令:github
composer require mikecao/flight
或者你能够直接下载,以后将Flight框架文件放入你的web目录中。web
2. 配置你的web服务器ajax
对于Apache服务器,编辑你的.htaccess
文件添加以下内容:正则表达式
RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php [QSA,L]
对于Nginx服务器,添加以下内容到你的server声明中:sql
server { location / { try_files $uri $uri/ /index.php; } }
3. 建立你的index.php
文件(示例)数据库
首先引入这个框架。
require 'flight/Flight.php';
接着定义一个路由而且注册一个函数去处理对应请求。
Flight::route('/', function(){ echo 'hello world!'; });
最后,启动框架。
Flight::start();
Flight中的路由是指将一个URL模式(pattern)匹配到一个回调函数中。
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'));
若是定义了多个路由,路由依照定义它们的顺序进行匹配。第一个匹配到该请求的路由将被调用。
在默认不指定的状况下,路由会对相应请求的全部Method(例如:GET POST PUT DELETE...)进行匹配。你能够经过在URL前面加一个方法标识符的方式来响应指定的Method。
Flight::route('GET /', function(){ echo 'I received a GET request.'; }); Flight::route('POST /', function(){ echo 'I received a POST request.'; });
你还可使用|
分隔符来映射多个Method到同一个回调中。
Flight::route('GET|POST /', function(){ echo 'I received either a GET or a POST request.'; });
在路由中你可使用正则表达式:
Flight::route('/user/[0-9]+', function(){ // 这个将匹配到 /user/1234 });
你能够在路由中指定命名参数,它们会被传递到你的回调函数里。
Flight::route('/@name/@id', function($name, $id){ echo "hello, $name ($id)!"; });
你也能够经过使用:
分隔符在命名变量中引入正则表达式
Flight::route('/@name/@id:[0-9]{3}', function($name, $id){ // 这个将匹配到 /bob/123 // 可是不会匹配到 /bob/12345 });
你能够经过将URL段(segments)包在括号里的方式来指定哪些命名参数是可选的。
Flight::route('/blog(/@year(/@month(/@day)))', function($year, $month, $day){ // 它将匹配以下URLS: // /blog/2012/12/10 // /blog/2012/12 // /blog/2012 // /blog });
任何没有被匹配到的可选参数将以NULL值传入。
匹配只发生在单独的URL段(segments)。若是你想匹配多段,可使用*
通配符。
Flight::route('/blog/*', function(){ // 这个将匹配到 /blog/2000/02/01 });
要将全部的请求路由到单一的回调上,你能够这么作:
Flight::route('*', function(){ // Do something });
当从一个被匹配到的回调函数中返回true
时,路由功能将继续执行,传递到下一个能匹配的路由中。
Flight::route('/user/@name', function($name){ // 检查某些条件 if ($name != "Bob") { // 延续到下一个路由 return true; } }); Flight::route('/user/*', function(){ // 这里会被调用到 });
若是你想检视匹配到的路由信息,能够请求将路由对象传递到你的回调函数中:你须要把
route方法的第三个参数设置成true
。这个路由对象老是会做为最后一个参数传入你的回调函数。
Flight::route('/', function($route){ // 匹配到的HTTP方法的数组 $route->methods; // 命名参数数组 $route->params; // 匹配的正则表达式 $route->regex; // Contains the contents of any '*' used in the URL pattern $route->splat; }, true);
Fligth被设计成一个可扩展的框架。这个框架带来了一系列的默认方法和组件,可是它容许你
映射你本身的方法,注册你本身的类,甚至能够重写已有的类和方法。
你可使用map
函数去映射你自定义的方法:
// 映射你本身的方法 Flight::map('hello', function($name){ echo "hello $name!"; }); // 调用你的自定义方法 Flight::hello('Bob');
你可使用register
函数去注册你本身的类:
// 注册你定义的类 Flight::register('user', 'User'); // 获得你定义的类的一个实例 $user = Flight::user();
register方法容许你向类的构造函数传递参数。因此当你加载自定义类的时候,它将会
预初始化(pre-initialized)。你能够经过一个追加的数组来传递定义的构造函数参数。
这是一个加载数据库链接的例子:
// 注册一个带有构造函数参数的类 Flight::register('db', 'PDO', array('mysql:host=localhost;dbname=test','user','pass')); // 获得你定义的类的一个实例 // 这里将建立一个带有你定义的参数的对象 // // new PDO('mysql:host=localhost;dbname=test','user','pass'); // $db = Flight::db();
若是你传递了额外的回调函数参数,它将会在类构造完以后当即执行。这就容许你为这个新对象去
执行任何的安装过程(set up procedures)。这个回调函数会被传递一个参数,就是这个新对象的实例。
// 这个回调函数将会传递到这个被构造的对象中 Flight::register('db', 'PDO', array('mysql:host=localhost;dbname=test','user','pass'), function($db){ $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); });
默认状况下,每次你加载一个类,你会获得一个共享的实例。若是要获得一个类的新实例,
简单的传递一个false
参数就好了。
// 类的共享实例 $shared = Flight::db(); // 类的新实例 $new = Flight::db(false);
须要记住的是,被映射的方法优先于被注册的类。若是你用相同的名字将它们都声明了,那么只有
映射的方法会被调用。
Flight容许你按照本身的须要去重写它的默认功能,而不用修改任何框架的代码。
例如,当Flight的路由功能没有匹配到一个URL时,它会调用notFound
方法,发出一个通用的
HTTP 404
响应。你可使用map
方法去重写这个行为。
Flight::map('notFound', function(){ // 显示自定义的404页面 include 'errors/404.html'; });
Flight也容许你替换这个框架的核心组件。例如你能够将默认的Router类替换成你自定义的类:
// 注册成你自定义的类 Flight::register('router', 'MyRouter'); // When Flight loads the Router instance, it will load your class // 当Flight加载Router实例时,将会加载到你自定义的类 $myrouter = Flight::router();
然而框架的方法诸如map
和register
是不可以被重写的。若是你尝试这么作的话你会获得一个error。
Flight容许你在方法调用以前和以后去过滤它。框架里没有任何你须要记住的预约义的钩子。你能够
过滤任何被映射的自定义方法和框架中的方法。
一个过滤器函数是像这样的:
function(&$params, &$output) { // Filter code }
经过传入的变量,你能够操做输入参数和/或输出参数。
这样作就能够在一个方法运行以前运行一个过滤器:
Flight::before('start', function(&$params, &$output){ // Do something });
这样作就能够在一个方法运行以后运行一个过滤器:
Flight::after('start', function(&$params, &$output){ // Do something });
你能够给任何函数添加任意数量的过滤器。它们将按照声明的顺序依次被调用。
这里是一个过滤器处理的例子:
// 映射一个自定义的方法 Flight::map('hello', function($name){ return "Hello, $name!"; }); // 添加一个前置的过滤器 Flight::before('hello', function(&$params, &$output){ // 操做这里的params $params[0] = 'Fred'; }); // 添加一个后置的过滤器 Flight::after('hello', function(&$params, &$output){ // 操做这里的output $output .= " Have a nice day!"; }); // 调用这个自定义方法 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'; // 以下将会终止这个过滤器链 return false; }); // 这里将不会获得调用 Flight::before('start', function(&$params, &$output){ echo 'three'; });
记住,核心函数诸如map
和register
是不可以被过滤的,由于它们是被直接调用而非动态调用的。
Flight容许你定义变量,使得它能在应用内的任何地方被使用。
// 保存你定义的变量 Flight::set('id', 123); // 在应用的其余地方使用 $id = Flight::get('id');
去检测一个变量是否被设置了能够这么作:
if (Flight::has('id')) { // Do something }
去清除一个变量你能够这么作:
// 清除这个id变量 Flight::clear('id'); // 清除全部的变量 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');
对网站来讲,拥有一个单独的可交换内容的布局(layout)模板文件是很常见的。要在布局中使用渲染的内容,
你能够给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模板引擎:
// 加载Smarty类库 require './Smarty/libs/Smarty.class.php'; // 将Smarty注册成视图类 // 同时传递一个回调函数,在加载过程当中配置Smarty Flight::register('view', 'Smarty', array(), function($smarty){ $smarty->template_dir = './templates/'; $smarty->compile_dir = './templates_c/'; $smarty->config_dir = './config/'; $smarty->cache_dir = './cache/'; }); // 模板中数据的赋值 Flight::view()->assign('name', 'Bob'); // 显示这个模板 Flight::view()->display('hello.tpl');
出于完备性,你还应该重写Flight的默认render方法:
Flight::map('render', function($template, $data){ Flight::view()->assign($data); Flight::view()->display($template); });
全部的errors和exceptions都会被Flight捕获,而后传到error
方法。该方法默认的行为是
发出一个带有错误信息的通用的HTTP 500 Internal Server Error
响应。
出于你本身的须要,你能够重写这个行为:
Flight::map('error', function(Exception $ex){ // 错误处理 echo $ex->getTraceAsString(); });
默认状况下,错误(errors)是不会被记录日志到web服务器的。你能够经过改变配置来容许记录。
Flight::set('flight.log_errors', true);
当一个URL没有被找到时,Flight将会调用notFound
方法。该方法默认的行为是
发出一个通用的HTTP 404 Not Found
响应并带有简单的说明信息。
出于你本身的须要,你能够重写这个行为:
Flight::map('notFound', function(){ // 处理not found });
你可使用redirect
方法将当前请求重定向到传入的新URL中。
Flight::redirect('/new/location');
默认状况下Flight会发出一个HTTP 303状态码。你能够选择设置一个自定义的状态码。
Flight::redirect('/new/location', 401);
Flight将HTTP请求封装到一个单独的对象中,你能够这样获取到它:
$request = Flight::request();
request对象提供了以下的属性:
url - 被请求的url base - The parent subdirectory of the URL method - 请求的Method (GET, POST, PUT, DELETE) referrer - 引用(referrer)的 URL ip - 客户点的IP地址 ajax - 是不是一个ajax请求 scheme - 服务器scheme (http, https) user_agent - 浏览器信息 type - Content-type length - Content-length query - 查询字符串参数(Query string parameters) data - Post数据或者JSON数据 cookies - Cookies数据 files - 上传的文件 secure - Whether the connection is secure accept - HTTP accept parameters proxy_ip - 客户端代理ip地址
你能够经过数组或对象的方式来获取query
,data
,cookies
和 files
属性。
也就是说,你能够这样获取到查询字符串参数(query string parameter):
$id = Flight::request()->query['id'];
或者你能够这样作:
$id = Flight::request()->query->id;
要获取原始的HTTP请求体数据,举例来讲当你正在处理PUT方法的请求时,你能够这么作:
$body = Flight::request()->getBody();
若是你发送application/json
类型的请求并带有数据{"id": 123}
时,它将被从data
属性中获取到。
$id = Flight::request()->data->id;
Flight为HTTP级别的缓存提供了内建的支持。若是知足缓存的条件,Flight将会返回一个
HTTP304 Not Modified
响应。当下一次客户端请求相同的资源时,它们会被提示去使用它们
本地的缓存版本。
你可使用lastModified
方法并传递一个UNIX时间戳去设置一个页面最后被修改的日期和时间。
客户端将继续使用它们的缓存直到last modified的值被改变了。
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请求,你能够选择传递查询参数名(query parameter name)用于定义你的回调函数:
Flight::jsonp(array('id' => 123), 'q');
因此,当使用?q=my_func
构造一个GET请求时,你应该会收到这样的输出:
my_func({"id":123});
若是你没有传递查询参数名(query parameter name)的话,它会有一个默认名jsonp
。
你可使用set
方法去设置配置的值,来自定义Flight的某些行为。
Flight::set('flight.log_errors', true);
下面是全部的可进行设置的配置列表:
flight.base_url - 覆盖该请求的base url。(默认值:null) flight.handle_errors - 容许Flight处理全部的内部错误。 (默认值:true) flight.log_errors - 向web服务器的错误日志文件里记录错误日志。 (默认值: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) // 添加类自动加载(autoloading)的路径 Flight::get($key) // 获取某个变量的值 Flight::set($key, $value) // 设置变量的值 Flight::has($key) // 某个变量是否被设值 Flight::clear([$key]) // 清除一个变量 Flight::init() // 初始化框架到默认的设定 Flight::app() // 获取整个应用对象的实例
Flight::start() // 开启框架(接收响应开始工做) Flight::stop() // 框架中止而且发送返回响应 Flight::halt([$code], [$message]) // 中止框架并返回一个可选的http状态码和信息 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]) // 运行HTTP Etag缓存 Flight::lastModified($time) // 运行HTTP last modified缓存 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();
也就是取代调用静态方法,你能够调用Engine对象实例里同名的方法。