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對象實例裏同名的方法。