1. 程式人生 > >Flightphp瞭解一下

Flightphp瞭解一下

Flight是什麼?

Flight是一個快速,簡易,可擴充套件的PHP框架。Flight能使你快速和輕鬆地建立RESTful Web應用。

require 'flight/Flight.php';

Flight::route('/', function(){
    echo 'hello world!';
});

Flight::start();

需求

Flight需要PHP 5.3或更高版本。

License

Flight is released under the MIT license.

安裝

1.框架下載

如果你在使用Composer

,你可以執行如下命令:

composer require mikecao/flight

或者你可以直接下載,之後將Flight框架檔案放入你的web目錄中。

2. 配置你的web伺服器

對於Apache伺服器,編輯你的.htaccess檔案新增如下內容:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]

對於Nginx伺服器,新增如下內容到你的server宣告中:

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'));

如果定義了多個路由,路由依照定義它們的順序進行匹配。第一個匹配到該請求的路由將被呼叫。

HTTP METHOD路由

在預設不指定的情況下,路由會對相應請求的所有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);

需要記住的是,被對映的方法優先於被註冊的類。如果你用相同的名字將它們都聲明瞭,那麼只有
對映的方法會被呼叫。

重寫(Overriding)

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();

然而框架的方法諸如mapregister是不能夠被重寫的。如果你嘗試這麼做的話你會得到一個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';
});

記住,核心函式諸如mapregister是不能夠被過濾的,因為它們是被直接呼叫而非動態呼叫的。

變數

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');

佈局(Layouts)

對網站來說,擁有一個單獨的可交換內容的佈局(layout)模板檔案是很常見的。要在佈局中使用渲染的內容,
你可以給render函式傳遞一個可選的引數。

Flight::render('header', array('heading' => 'Hello'), 'header_content');
Flight::render('body', array('body' => 'World'), 'body_content');

緊接著你的檢視就有了命名為header_contentbody_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);
});

錯誤(Error)處理

錯誤(Errors)和異常(Exceptions)

所有的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);

Not Found

當一個URL沒有被找到時,Flight將會呼叫notFound方法。該方法預設的行為是
發出一個通用的HTTP 404 Not Found響應並帶有簡單的說明資訊。

出於你自己的需要,你可以重寫這個行為:

Flight::map('notFound', function(){
    // 處理not found
});

重定向(Redirects)

你可以使用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,cookiesfiles屬性。

也就是說,你可以這樣獲取到查詢字串引數(query string parameter):

$id = Flight::request()->query['id'];

或者你可以這樣做:

$id = Flight::request()->query->id;

請求體原始資料(RAW Request Body)

要獲取原始的HTTP請求體資料,舉例來說當你正在處理PUT方法的請求時,你可以這麼做:

$body = Flight::request()->getBody();

JSON 輸入

如果你傳送application/json型別的請求並帶有資料{"id": 123}時,它將被從data屬性中獲取到。

$id = Flight::request()->data->id;

HTTP快取

Flight為HTTP級別的快取提供了內建的支援。如果滿足快取的條件,Flight將會返回一個
HTTP304 Not Modified響應。當下一次客戶端請求相同的資源時,它們會被提示去使用它們
本地的快取版本。

Last-Modified

你可以使用lastModified方法並傳遞一個UNIX時間戳去設定一個頁面最後被修改的日期和時間。
客戶端將繼續使用它們的快取直到last modified的值被改變了。

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請求,你可以選擇傳遞查詢引數名(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響應

任何通過mapregister新增的自定義方法都可以被過濾。

框架的例項

替代將Flight執行成一個全域性的靜態類,你可以選擇將它執行成一個物件的例項。

require 'flight/autoload.php';

use flight\Engine;

$app = new Engine();

$app->route('/', function(){
    echo 'hello world!';
});

$app->start();

也就是取代呼叫靜態方法,你可以呼叫Engine物件例項裡同名的方法。

轉載於:https://www.jianshu.com/p/06e2c20bc0dc