
一個功能強大且易於使用的 PHP 微框架,旨在幫助您快速建立動態且健壯的 Web 應用程式!
F3(我們親切地稱呼它)壓縮在一個約 65KB 的文件中,為您提供了堅實的基礎、成熟的程式碼庫以及編寫 Web 應用程式的嚴肅方法。其底層是一個易於使用的 Web 開發工具包、高效能 URL 路由和快取引擎、內建程式碼突出顯示以及對多語言應用程式的支援。它重量輕、易於使用且速度快。最重要的是,它不會妨礙您。
無論您是 PHP 程式設計師的新手還是專家,F3 都會讓您立即上手並運行。沒有不必要和繁瑣的安裝過程。無需複雜的配置。沒有複雜的目錄結構。現在就是開始以簡單的方式開發 Web 應用程式的最佳時機!
F3 支援現成的 SQL 和 NoSQL 資料庫:MySQL、SQLite、MSSQL/Sybase、PostgreSQL、DB2 和 MongoDB。它還配備了強大的物件關係映射器,用於資料抽象化和建模,與框架一樣輕量級。無需配置。
這還不是全部。 F3 與其他擴展其功能的可選插件打包在一起:-
與其他框架不同,F3 的目標是可用——這並不常見。
該框架及其軟體架構方法背後的理念是實現結構組件的極簡主義,避免應用程式複雜性並在程式碼優雅、應用程式效能和程式設計師生產力之間取得平衡。


F3擁有穩定的企業級架構。無與倫比的性能、用戶友好的功能和輕巧的佔地面積。您還能要求什麼?要取得此軟體包,只需下載此軟體包或訪問 fatfree-core 儲存庫以查找最新的邊緣版本。
對於所有作曲家使用者:
composer create-project bcosca/fatfree啟動一個新項目composer require bcosca/fatfree-core將 fatfree 加入到現有項目中強烈建議有經驗的用戶使用最新版本開發新應用程序,以利用更新的程式碼庫和持續的改進。
最新的使用者指南和詳細的 API 文件以及大量程式碼範例和圖形指南可以在 fatfreeframework.com/ 上找到。
當然,這個方便的線上參考是由 F3 提供支援的!它展示了該框架的功能和性能。現在就檢查一下。如果您想直接在 github 上閱讀,可以在 github.com/F3Community/F3com-data 找到網站內容
設計師知道他已經達到了完美,不是當沒有什麼可以添加的時候,而是當沒有什麼可以刪除的時候。 ——安東尼‧德‧聖艾克蘇佩里
Fat-Free Framework 讓您可以輕鬆快速建立整個網站。 F3 具有與現代 Javascript 工具包和函式庫相同的功能和簡潔性,可以幫助您編寫更美觀、更可靠的 PHP 程式。只要看一眼你的 PHP 原始碼,任何人都會發現它很容易理解,你可以用這麼少的幾行程式碼完成多少工作,以及結果有多強大。
F3 是文件最好的框架之一。學習它幾乎不需要任何成本。沒有嚴格的難以導航的目錄結構和煩人的程式步驟。無需大量配置選項即可在瀏覽器中顯示'Hello, World' 。無脂給您很大的自由和風格,讓您在更短的時間內輕鬆完成更多的工作。
F3 的聲明式程式設計方法讓新手和專家都可以輕鬆理解 PHP 程式碼。如果您熟悉 Ruby 程式語言,您會注意到 Fat-Free 和 Sinatra 微框架之間的相似之處,因為它們都採用簡單的領域特定語言來實作 ReSTful Web 服務。但與 Sinatra 及其 PHP 版本(Fitzgerald、Limonade、Glue 等等)不同,Fat-Free 不僅僅只處理路由和請求。視圖可以是任何形式,例如純文字、HTML、XML 或電子郵件訊息。該框架配備了快速且易於使用的模板引擎。 F3 還可以與其他模板引擎無縫協作,包括 Twig、Smarty 和 PHP 本身。模型與 F3 的資料映射器和 SQL 幫助程式進行通信,以便與各種資料庫引擎進行更複雜的互動。其他插件進一步擴展了基本功能。它是一個完整的 Web 開發框架 - 功能強大!
將分發包的內容解壓縮到硬碟中的任意位置。預設情況下,框架檔案和選用外掛程式位於lib/路徑中。以您想要的方式組織您的目錄結構。為了提高安全性,您可以將預設資料夾移至無法透過 Web 存取的路徑。刪除不需要的插件。您稍後可以隨時恢復它們,F3 將自動偵測它們的存在。
重要提示:如果您的應用程式使用 APC、Memcached、WinCache、XCache 或檔案系統緩存,請先清除所有快取條目,然後再用新版本的框架覆蓋舊版本的框架。
確保您執行的是正確版本的 PHP。 F3 不支援 PHP 7.2 之前的版本。您會到處遇到語法錯誤(誤報),因為過時的 PHP 版本不支援新的語言結構和閉包/匿名函數。要找到答案,請開啟控制台(GNU/Linux 上的bash shell,或 Windows 上的cmd.exe ):-
/path/to/php -v
PHP 會讓您知道您正在運行哪個特定版本,並且您應該得到與此類似的內容:-
PHP 7.4.21 (cli) (built: Jul 27 2021 15:56:07) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
with Xdebug v2.9.8, Copyright (c) 2002-2020, by Derick Rethans
如果需要,請升級,如果您已跳到 PHP 7.4 或更高版本,請返回此處。 Fatfree 至少需要 PHP 7.2 才能運作。如果您需要託管服務提供者,請嘗試以下服務之一:
是時候開始編寫我們的第一個應用程式了:-
$ f3 = require ( ' path/to/base.php ' );
$ f3 -> route ( ' GET / ' ,
function () {
echo ' Hello, world! ' ;
}
);
$ f3 -> run ();在第一行加入適當的路徑作為base.php前綴。將以上程式碼片段儲存為 Web 根資料夾中的index.php 。我們已經寫了第一個網頁。
使用作曲家?然後只需執行composer require bcosca/fatfree並使用以下命令:
require ' vendor/autoload.php ' ;
$ f3 = Base:: instance ();
$ f3 -> route ( ' GET / ' ,
function () {
echo ' Hello, world! ' ;
}
);
$ f3 -> run ();第一個命令告訴 PHP 解釋器您希望應用程式可以使用該框架的功能和特性。 $f3->route()方法通知 Fat-Free 在斜線 ( / ) 指示的相對 URL 處有可用的網頁。任何訪問您位於http://www.example.com/網站的人都會看到'Hello, world!'訊息,因為 URL /相當於根頁面。若要建立從根頁面分支的路由(例如http://www.example.com/inside/ ,您可以使用簡單的GET /inside字串定義另一個路由。
上述路由告訴框架僅在使用 HTTP GET方法接收到 URL 請求時才渲染頁面。包含表單的更複雜的網站使用其他 HTTP 方法,例如POST ,您也可以將其實作為$f3->route()規範的一部分。
如果框架發現位於根 URL /網頁的傳入請求,它會自動將請求路由到回呼函數,該函數包含處理請求和呈現適當的 HTML 內容所需的程式碼。在此範例中,我們僅發送字串'Hello, world!'到使用者的 Web 瀏覽器。
所以我們已經建立了我們的第一條路線。但這並沒有多大作用,只是讓 F3 知道有一個進程可以處理它並且有一些文字要顯示在使用者的 Web 瀏覽器上。如果您的網站上有很多頁面,則需要為每個群組設定不同的路由。現在,讓我們保持簡單。為了指示框架開始等待請求,我們發出$f3->run()指令。
無法運行範例?如果您在伺服器上執行這個簡單的程式時遇到困難,您可能需要稍微調整一下 Web 伺服器設定。查看下一節中的範例 Apache 配置(以及 Nginx 和 Lighttpd 等效項)。
仍有問題嗎?確保$f3 = require('path/to/base.php');賦值出現在腳本中的任何輸出之前。 base.php會修改 HTTP 標頭,因此在此分配之前輸出到瀏覽器的任何字元都會導致錯誤。
我們的第一個例子並不難接受,不是嗎?如果您喜歡無脂湯的味道多一點,請在$f3->run()命令之前插入另一條路線:-
$ f3 -> route ( ' GET /about ' ,
function () {
echo ' Donations go to a local charity... us! ' ;
}
);您不想讓函數名稱弄亂全域命名空間嗎? Fat-Free 識別將路由處理程序對應到 OOP 類別和方法的不同方式:-
class WebPage {
function display () {
echo ' I cannot object to an object ' ;
}
}
$ f3 -> route ( ' GET /about ' , ' WebPage->display ' );HTTP 請求也可以路由到靜態類別方法:-
$ f3 -> route ( ' GET /login ' , ' Auth::login ' );傳遞的參數總是作為第二個參數提供:
$ f3 -> route ( ' GET /hello/@name ' , ' User::greet ' );
class User {
public static function greet ( $ f3 , $ args ) { // $ args is type of Array
echo " Hello " . $ args [ ' name ' ];
}
}如果提供的名稱參數為foo (/hello/foo),則會顯示下列輸出:
Hello foo
作為 Fat-Free 強大的領域特定語言 (DSL) 的演示,您可以指定單一路由來處理不同的可能性:-
$ f3 -> route ( ' GET /brew/@count ' ,
function ( $ f3 ) {
echo $ f3 -> get ( ' PARAMS.count ' ). ' bottles of beer on the wall. ' ;
}
);此範例顯示如何指定標記@count來表示 URL 的一部分。該框架將提供與/ '98 bottles of beer on the wall' /brew/前綴匹配的任何請求 URL,例如/brew/99 '99 bottles of beer on the wall' /brew/98等。 Fat-Free 也將接受/brew/unbreakable的頁面請求。 (預計這會顯示'unbreakable bottles of beer on the wall' 。)當指定這樣的動態路由時,Fat-Free 會自動使用 URL 中捕獲的字串值填入全域PARAMS數組變數。回呼函數內的$f3->get()呼叫檢索框架變數的值。您當然可以在程式碼中應用此方法作為表示或業務邏輯的一部分。但我們稍後會更詳細地討論這個問題。
請注意,Fat-Free 瞭解數組點表示法。您可以在程式碼中使用PARAMS['count']常規表示法,這很容易出現拼字錯誤和大括號不平衡。在視圖和範本中,框架允許@PARAMS.count表示法,這有點類似 Javascript。 (稍後我們將介紹視圖和模板。)
這是在請求模式中存取令牌的另一種方法:-
$ f3 -> route ( ' GET /brew/@count ' ,
function ( $ f3 , $ params ) {
echo $ params [ ' count ' ]. ' bottles of beer on the wall. ' ;
}
);您可以使用星號 ( * ) 接受/brew路由之後的任何 URL - 如果您並不真正關心路徑的其餘部分:-
$ f3 -> route ( ' GET /brew/* ' ,
function () {
echo ' Enough beer! We always end up here. ' ;
}
);需要考慮的重要一點是:如果您在同一個應用程式中同時使用GET /brew/@count和GET /brew/* ,您將會對 Fat-Free(以及您自己)感到困惑。使用其中之一。另一件事:Fat-Free 將GET /brew視為獨立且不同於路線GET /brew/@count 。每個可以有不同的路由處理程序。
等一下 - 在前面的所有範例中,我們從未真正在硬碟中建立任何目錄來儲存這些路由。簡短的回答是:我們不必這樣做。所有 F3 路由都是虛擬的。它們不反映我們的硬碟資料夾結構。如果您有不使用框架的程式或靜態檔案(圖片、CSS 等)—只要這些檔案的路徑不會與應用程式中定義的任何路由衝突—您的 Web 伺服器軟體會將它們傳送到使用者的瀏覽器,前提是伺服器配置正確。
定義路線時,您可以為其指定名稱。在程式碼和範本中使用路由名稱,而不是鍵入的 URL。那麼如果你需要改變你的url來取悅行銷霸主,你只需要在定義路由的地方進行改變。路由名稱必須遵循 php 變數命名規則(沒有點、破折號或連字號)。
讓我們命名一條路線:-
$ f3 -> route ( ' GET @beer_list: /beer ' , ' Beer->list ' );名稱插入在路由 VERB(本範例中為GET )之後,前面有@符號,並用冒號:符號與 URL 部分分隔。如果可以更輕鬆地閱讀程式碼,您可以在冒號後插入空格(如此處所示)。
若要存取範本中的命名路由,請取得命名路由的值作為ALIASES hive 陣列的鍵:-
< a href =" {{ @ALIASES.beer_list }} " > View beer list </ a >若要將訪客重新導向至新 URL,請在reroute()方法中呼叫命名路由,如下所示:
// a named route is a string value
$ f3 -> reroute ( ' @beer_list ' ); // note the single quotes如果您在路線中使用令牌,F3 會將這些令牌替換為其目前值。如果您想在呼叫重新路由之前更改令牌的值,請將其作為第二個參數傳遞。
$ f3 -> route ( ' GET @beer_list: /beer/@country ' , ' Beer->bycountry ' );
$ f3 -> route ( ' GET @beer_list: /beer/@country/@village ' , ' Beer->byvillage ' );
// a set of key - value pairs is passed as argument to named route
$ f3 -> reroute ( ' @beer_list(@country=Germany) ' );
// if more than one token needed
$ f3 -> reroute ( ' @beer_list(@country=Germany,@village=Rhine) ' );如果您的字元不符合 RFC 1738 格式正確的 URL 準則,請記得對您的參數urlencode() 。
PHP 的最新穩定版本有自己內建的Web 伺服器。使用以下配置啟動它:-
php -S localhost:80 -t /var/www/
上面的指令將開始將所有請求路由到 Web 根目錄/var/www 。如果收到對檔案或資料夾的傳入 HTTP 請求,PHP 將在 Web 根目錄中尋找它,如果找到則將其傳送到瀏覽器。否則,PHP 將載入預設的index.php (包含啟用 F3 的程式碼)。
如果您使用的是 Apache,請確保在 apache.conf(或 httpd.conf)檔案中啟動 URL 重寫模組 (mod_rewrite)。您還應該建立一個包含以下內容的 .htaccess 檔案:-
# Enable rewrite engine and route requests to framework
RewriteEngine On
# Some servers require you to specify the `RewriteBase` directive
# In such cases, it should be the path (relative to the document root)
# containing this .htaccess file
#
# RewriteBase /
RewriteRule ^(tmp)/|.ini$ - [R=404]
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php [L,QSA]
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]這個腳本告訴 Apache,每當 HTTP 請求到達時,如果找不到實體檔案 ( !-f ) 或路徑 ( !-d ) 或符號連結 ( !-l ),它應該將控制權轉移到index.php ,其中包含我們的主/前端控制器,然後呼叫框架。
包含上述 Apache 指令的.htaccess file應始終與index.php位於同一資料夾中。
您還需要設定 Apache,以便它知道index.php在硬碟中的實體位置。典型的配置是:-
DocumentRoot " /var/www/html "
< Directory "/var/www/html">
Options -Indexes +FollowSymLinks +Includes
AllowOverride All
Order allow,deny
Allow from All
</ Directory >如果您同時開發多個應用程序,則虛擬主機配置更易於管理:-
NameVirtualHost *
< VirtualHost *>
ServerName site1.com
DocumentRoot " /var/www/site1 "
< Directory "/var/www/site1">
Options -Indexes +FollowSymLinks +Includes
AllowOverride All
Order allow,deny
Allow from All
</ Directory >
</ VirtualHost >
< VirtualHost *>
ServerName site2.com
DocumentRoot " /var/www/site2 "
< Directory "/var/www/site2">
Options -Indexes +FollowSymLinks +Includes
AllowOverride All
Order allow,deny
Allow from All
</ Directory >
</ VirtualHost >每個ServerName (在我們的範例中為site1.com和site2.com )必須列在/etc/hosts檔案中。在 Windows 上,您應該編輯C:/WINDOWS/system32/drivers/etc/hosts 。可能需要重新啟動才能使變更生效。然後,您可以將 Web 瀏覽器指向網址http://site1.com或http://site2.com 。虛擬主機使您的應用程式更容易部署。
對於 Nginx 伺服器,以下是建議的配置(將 ip_address:port 替換為您環境的 FastCGI PHP 設定):-
server {
root /var/www/html;
location / {
index index.php index.html index.htm;
try_files $uri $uri / /index.php? $query_string ;
}
location ~ .php$ {
fastcgi_pass ip_address:port;
include fastcgi_params;
}
}Lighttpd 伺服器的設定方式類似:-
$HTTP["host"] =~ "www.example.com$" {
url.rewrite-once = ( "^/(.*?)(?.+)?$"=>"/index.php/$1?$2" )
server.error-handler-404 = "/index.php"
}
安裝與您的 Windows 版本相對應的 URL 重寫模組和適當的 .NET 框架。然後在應用程式根目錄中建立一個名為web.config的文件,其中包含以下內容:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Application" stopProcessing="true">
<match url=".*" ignoreCase="false" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
</conditions>
<action type="Rewrite" url="index.php" appendQueryString="true" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
那麼讓我們回到編碼。您可以聲明頁面已過時並將訪客重新導向到另一個網站/頁面:-
$ f3 -> route ( ' GET|HEAD /obsoletepage ' ,
function ( $ f3 ) {
$ f3 -> reroute ( ' /newpage ' );
}
);如果有人嘗試使用 HTTP GET 或 HEAD 請求存取 URL http://www.example.com/obsoletepage ,框架會將使用者重新導向至 URL:http: http://www.example.com/newpage如下所示上面的例子。您也可以將使用者重新導向到另一個站點,例如$f3->reroute('http://www.anotherexample.org/'); 。
當您需要在網站上進行一些維護工作時,重新路由尤其有用。您可以有一個路由處理程序,通知您的訪客您的網站在短時間內處於離線狀態。
HTTP 重定向是必不可少的,但它們也可能很昂貴。如果您可以透過呼叫處理目標路由的函數或方法來引導應用程式的流程,請盡可能避免使用$f3->reroute()將使用者傳送到同一網站上的另一個頁面。但是,此方法不會變更使用者 Web 瀏覽器網址列上的 URL。如果這不是您想要的行為,而您確實需要將使用者傳送到另一個頁面,例如成功提交表單或使用者經過驗證後,Fat-Free 會傳送HTTP 302 Found標頭。對於重新路由到另一個頁面或網站的所有其他嘗試,框架會傳送HTTP 301 Moved Permanently標頭。
在執行時,只要 Fat-Free 發現傳入的 HTTP 請求與應用程式中定義的任何路由不匹配,就會自動產生 HTTP 404 錯誤。但是,在某些情況下您需要自己觸發它。
以定義為GET /dogs/@breed路由為例。您的應用程式邏輯可能涉及搜尋資料庫並嘗試檢索與傳入 HTTP 請求中的@breed值相對應的記錄。由於存在@breed令牌,Fat-Free 將接受/dogs/前綴之後的任何值,因此當程式在我們的資料庫中找不到任何符合項目時,有必要以程式設計方式顯示HTTP 404 Not Found訊息。為此,請使用以下命令:-
$ f3 -> error ( 404 );Fat-Free 的體系結構基於以下概念:HTTP URI 表示抽象 Web 資源(不限於 HTML),並且每個資源都可以從一種應用程式狀態轉移到另一種應用程式狀態。因此,F3 對您建立應用程式的方式沒有任何限制。如果您喜歡使用模型-視圖-控制器模式,F3 可以幫助您劃分應用程式元件以遵循此範例。另一方面,該框架還支援資源-方法-表示模式,並且實現起來更加簡單。
這是 ReST 介面的範例:-
class Item {
function get () {}
function post () {}
function put () {}
function delete () {}
}
$ f3 = require ( ' lib/base.php ' );
$ f3 -> map ( ' /cart/@item ' , ' Item ' );
$ f3 -> run (); Fat-Free 的$f3->map()方法透過將路由中的 HTTP 方法對應到物件或 PHP 類別的等效方法來提供 ReST 介面。如果您的應用程式收到傳入的 HTTP 請求(例如GET /cart/123 ,Fat-Free 會自動將控制權轉移到物件或類別的get()方法。另一方面, POST /cart/123請求將被路由到Item類別的post()方法。
注意:瀏覽器不會以常規 HTML 形式實作 HTTP PUT和DELETE方法。這些和其他 ReST 方法( HEAD和CONNECT )只能透過對伺服器的 AJAX 呼叫來存取。
如果框架接收到映射到類別未實現的方法的路由的 HTTP 請求(可能您在路由對映中犯了錯誤,或尚未編寫該方法),它會產生HTTP 405 Method Not Allowed錯誤。
如果用戶端請求 URL 資源的 HTTP OPTIONS ,F3 將使用適當的 HTTP 標頭回應,該標頭指示資源允許使用哪些方法(HEAD、GET、PUT 等)。框架不會將OPTIONS請求對應到類別。
Fat-Free 有一種僅在您需要時載入類別的方法,因此它們不會佔用比應用程式特定部分所需的記憶體更多的記憶體。而且您不必編寫一長串include或require語句來載入保存在不同檔案和不同位置的 PHP 類別。該框架可以自動為您完成此操作。只需將檔案(每個檔案一個類別)保存在資料夾中,並告訴框架在呼叫類別中的方法後自動載入適當的檔案:-
$ f3 -> set ( ' AUTOLOAD ' , ' autoload/ ' );您可以透過變更AUTOLOAD全域變數的值來為自動載入的類別指派不同的位置。您還可以有多個自動載入路徑。如果您將類別組織在不同的資料夾中,則可以指示框架在呼叫靜態方法或實例化物件時自動載入適當的類別。這樣修改AUTOLOAD變數:-
$ f3 -> set ( ' AUTOLOAD ' , ' admin/autoload/; user/autoload/; default/ ' );重要提示:除了 .php 副檔名之外,類別名稱和檔案名稱必須相同,框架才能正確自動載入您的類別。該檔案的基名必須與您的類別呼叫相同,例如,當 F3 在您的應用程式中偵測到new FooBarBaz語句時,它將尋找Foo/BarBaz.php或foo/barbaz.php 。
AUTOLOAD允許類別層次結構駐留在名稱相似的子資料夾中,因此如果您希望框架自動載入以下方式呼叫的命名空間類別:-
$ f3 -> set ( ' AUTOLOAD ' , ' autoload/ ' );
$ obj = new Gadgets iPad ;您可以建立遵循相同結構的資料夾層次結構。假設/var/www/html/是您的 Web 根目錄,那麼 F3 將在/var/www/html/autoload/gadgets/ipad.php中尋找該類別。檔案ipad.php應具有以下最少程式碼:-
namespace Gadgets ;
class iPad {}請記住:Fat-Free 中的所有目錄名稱都必須以斜線結尾。您可以為自動載入器指定搜尋路徑,如下所示:-
$ f3 -> set ( ' AUTOLOAD ' , ' main/;aux/ ' );F3 是一個命名空間感知框架,可讓您使用命名空間類別中的方法作為路由處理程序,並且有多種方法可以實現這一點。呼叫靜態方法:-
$ f3 -> set ( ' AUTOLOAD ' , ' classes/ ' );
$ f3 -> route ( ' GET|POST / ' , ' MainHome::show ' );上面的程式碼將會呼叫Main命名空間中Home類別的靜態show()方法。 Home類別必須保存在classes/main/home.php資料夾中才能自動載入。
如果您喜歡使用物件:-
$ f3 -> route ( ' GET|POST / ' , ' MainHome->show ' );將在運行時實例化Home類別並隨後呼叫show()方法。
F3 有幾個路由事件偵聽器,可以幫助您改善控制器類別的流程和結構。假設您有一條定義如下的路線:-
$ f3 -> route ( ' GET / ' , ' Main->home ' );如果應用程式收到與上述路由相符的 HTTP 請求,F3 會實例化Main ,但在執行home()方法之前,框架會在此類中尋找名為beforeRoute()方法。如果找到,F3 會在將控制權轉移到home()方法之前執行beforeRoute()事件處理程序中所包含的程式碼。一旦完成,框架就會尋找afterRoute()事件處理程序。與beforeRoute()一樣,如果定義了該方法,則會執行該方法。
這是 F3 的另一個好東西:-
$ f3 -> route ( ' GET /products/@action ' , ' Products->@action ' );如果您的應用程式收到/products/itemize等請求,F3 將從 URL 中提取'itemize'字串,並將其傳遞給路由處理程序中的@action令牌。然後,F3 將尋找名為Products類別並執行itemize()方法。
動態路由處理程序可能有多種形式:-
// static method
$ f3 -> route ( ' GET /public/@genre ' , ' Main::@genre ' );
// object mode
$ f3 -> route ( ' GET /public/@controller/@action ' , ' @controller->@action ' );如果 F3 無法將控制權轉移到與目前路由關聯的類別或方法(即未定義的類別或方法),則 F3 在執行時會觸發HTTP 404 Not Found錯誤。
路由模式可能包含指示框架根據 HTTP 請求類型做出路由決策的修飾符:-
$ f3 -> route ( ' GET /example [ajax] ' , ' Page->getFragment ' );
$ f3 -> route ( ' GET /example [sync] ' , ' Page->getFull ' );只有當伺服器收到X-Requested-With: XMLHttpRequest標頭(AJAX 物件)時,第一個語句才會將 HTTP 請求路由到Page->getFragment()回呼。如果偵測到普通(同步)請求,F3 將簡單地下拉到下一個匹配模式,在這種情況下,它執行Page->getFull()回呼。
如果在路由模式中沒有定義修飾符,則 AJAX 和同步請求類型都會路由到指定的處理程序。
路線模式修飾符也可以被$f3->map()辨識。
Fat-Free 中定義的變數是全域性的,也就是它們可以被任何 MVC 元件存取。框架全域變數與 PHP 全域變數不同。名為content F3 變數與 PHP 的$content不同。 F3 本身就是一種特定於領域的語言,並為系統和應用程式變數維護自己單獨的符號表。與每個精心設計的物件導向程式一樣,該框架不會因為可能與任何應用程式發生衝突的常數、變數、函數或類別而污染 PHP 全域命名空間。與其他框架不同,F3 不使用 PHP 的define()語句。所有框架常數都僅限於類別。
為無脂變數賦值:
$ f3 -> set ( ' var ' ,value); // or
$ f3 -> var =value;
$ f3 -> set ( ' hello.world ' , ' good morning ' ); // translates to : 'hello' == array ( 'world' = > 'good morning' )
$ f3 ->{ ' hello.world ' }= ' good morning ' ; // same as prior statement注意: Fat-Free 變數接受所有 PHP 資料類型,包括物件和匿名函數。
要一次設定多個變數:
$ f3 -> mset (
[
' foo ' => ' bar ' ,
' baz ' => 123
]
);要檢索名為var的框架變數的值:-
echo $ f3 -> get ( ' var ' ); // or
echo $ f3 -> var ;如果您不再需要它,請從記憶體中刪除無脂肪變數(丟棄它,這樣它就不會幹擾您的其他函數/方法),請使用以下方法:-
$ f3 -> clear ( ' var ' ); // or
unset( $ f3 -> var );要查明變數是否先前已定義:-
$ f3 -> exists ( ' var ' ) //
isset ( $ f3 -> var )F3 維護自己的框架和應用程式變數符號表,這些符號表獨立於 PHP。一些變數映射到 PHP 全域變數。 Fat-Free 的SESSION相當於$_SESSION ,而REQUEST對應到$_REQUEST 。建議使用框架變數而不是 PHP 變量,以幫助您跨不同函數、類別和方法進行資料傳輸。它們還有其他優點:-
SESSION的無脂肪等效項也會改變 PHP 的底層$_SESSION 。改變後者也會改變對應的框架。 Fat-Free 不僅僅維護變數及其值的愚蠢儲存。它還可以自動化會話管理和其他事情。透過 F3 的SESSION變數指派或擷取值會自動啟動會話。如果您直接使用$_SESSION (或與會話相關的函數),而不是框架變數SESSION ,您的應用程式將負責管理會話。
通常,框架變數在 HTTP 請求之間不會持續存在。只有映射到 PHP 的$_SESSION和$_COOKIE全域變數的SESSION和COOKIE (及其元素)不受 HTTP 無狀態特性的影響。
Fat-Free 在內部使用了幾個預先定義的全域變量,您當然可以在您的應用程式中使用它們。確保你知道自己在做什麼。更改一些 Fat-Free 全域變數可能會導致意外的框架行為。
這個框架有幾個變數可以幫助您保持檔案和目錄結構井井有條。我們已經了解如何使用AUTOLOAD自動載入類別。有一個UI全域變量,其中包含指向 HTML 視圖/模板位置的路徑。 DEBUG是您在應用程式開發過程中經常使用的另一個變量,它用於設定錯誤追蹤的詳細程度。
如果您需要內建框架變數的完整列表,請參閱快速參考。
框架變數可以包含任意數量的字母、數字和底線。它必須以字母字元開頭且不能有空格。變數名稱區分大小寫。
F3 對內部預先定義的全域變數使用全部大寫。沒有什麼可以阻止您在自己的程式中使用由全大寫組成的變數名稱,但作為一般規則,在設定自己的變數時堅持使用小寫(或駝峰式),這樣就可以避免與當前和未來的框架版本發生任何可能的衝突。
您不應使用 PHP 保留字(例如if 、 for 、 class 、 default等)作為框架變數名稱。這些可能會導致不可預測的結果。
F3 也提供了許多工具來幫助您處理框架變數。
$ f3 -> set ( ' a ' , ' fire ' );
$ f3 -> concat ( ' a ' , ' cracker ' );
echo $ f3 -> get ( ' a ' ); // returns the string 'firecracker'
$ f3 -> copy ( ' a ' , ' b ' );
echo $ f3 -> get ( ' b ' ); // returns the same string : 'firecracker'F3 也提供了一些處理數組變數的原始方法:-
$ f3 -> set ( ' colors ' ,[ ' red ' , ' blue ' , ' yellow ' ]);
$ f3 -> push ( ' colors ' , ' green ' ); // works like PHP ' s array_push ()
echo $ f3 -> pop ( ' colors ' ); // returns 'green'
$ f3 -> unshift ( ' colors ' , ' purple ' ); // similar to array_unshift ()
echo $ f3 -> shift ( ' colors ' ); // returns 'purple'
$ f3 -> set ( ' grays ' ,[ ' light ' , ' dark ' ]);
$ result = $ f3 -> merge ( ' colors ' , ' grays ' ); // merges the two arrays與其他具有嚴格資料夾結構的框架不同,F3 為您提供了很大的靈活性。您可以擁有如下所示的資料夾結構(全大寫的括號內的單字表示需要調整的 F3 框架變數):-
/ (your Web root, where index.php is located)
app/ (application files)
dict/ (LOCALES, optional)
controllers/
logs/ (LOGS, optional)
models/
views/ (UI)
css/
js/
lib/ (you can store base.php here)
tmp/ (TEMP, used by the framework)
cache/ (CACHE)
您可以隨意以您想要的方式組織您的文件和目錄。只需設定適當的 F3 全域變數即可。如果您想要一個真正安全的站點,Fat-Free 甚至允許您將所有檔案儲存在無法透過 Web 存取的目錄中。唯一的要求是將index.php 、 .htaccess和公用檔案(例如 CSS、JavaScript、圖片等)保留在瀏覽器可見的路徑中。
Fat-Free 產生自己的 HTML 錯誤頁面,並帶有堆疊追蹤來幫助您進行偵錯。這是一個例子:-
內部伺服器錯誤
strpos() 需要至少 2 個參數,給定 0 個
• var/html/dev/main.php:96 strpos() • var/html/dev/index.php:16 Base->run()
如果您覺得它有點太簡單或希望在錯誤發生時執行其他操作,您可以建立自己的自訂錯誤處理程序:-
$ f3 -> set ( ' ONERROR ' ,
function ( $ f3 ) {
// custom error handler code goes here
// use this if you want to display errors in a
// format consistent with your site ' s theme
echo $ f3 -> get ( ' ERROR.status ' );
}
); F3 維護一個全域變量,其中包含應用程式中發生的最新錯誤的詳細資訊。 ERROR變數是一個結構如下的陣列:-
ERROR.code - displays the error code (404, 500, etc.)
ERROR.status - header and page title
ERROR.text - error context
ERROR.trace - stack trace
在開發應用程式時,最好將偵錯等級設為最大,以便您可以追蹤所有錯誤的根本原因:-
$ f3 -> set ( ' DEBUG ' , 3 );只需將命令插入應用程式的引導序列中即可。
一旦您的應用程式準備好發布,只需從您的應用程式中刪除該聲明,或將其替換為:-
$ f3 -> set ( ' DEBUG ' , 0 );這將抑制任何系統產生的 HTML 錯誤頁面中的堆疊追蹤輸出(因為您的網站訪客不會看到它)。
DEBUG值範圍為 0(堆疊追蹤被抑制)到 3(最詳細)。
別忘了!堆疊追蹤可能包含路徑、檔案名稱、資料庫命令、使用者名稱和密碼。如果在生產環境中未能將DEBUG全域變數設為 0,則可能會使您的網站面臨不必要的安全風險。
如果您的應用程式需要使用者可配置,F3 提供了一種方便的方法來讀取設定檔來設定您的應用程式。這樣,您和您的用戶就可以調整應用程序,而無需更改任何 PHP 程式碼。
而不是建立包含以下範例程式碼的 PHP 腳本:-
$ f3 -> set ( ' num ' , 123 );
$ f3 -> set ( ' str ' , ' abc ' );
$ f3 -> set ( ' hash ' ,[ ' x ' => 1 , ' y ' => 2 , ' z ' => 3 ]);
$ f3 -> set ( ' items ' ,[ 7 , 8 , 9 ]);
$ f3 -> set ( ' mix ' ,[ ' this ' , 123.45 , FALSE ]);您可以建立一個執行相同操作的設定檔:-
[globals]
num =123
; this is a regular string
str =abc
; another way of assigning strings
str = " abc "
; this is an array
hash[x]=1
hash[y]=2
hash[z]=3
; dot-notation is recognized too
hash.x =1
hash.y =2
hash.z =3
; this is also an array
items =7,8,9
; array with mixed elements
mix = " this " ,123.45,FALSE您可以指示框架載入設定檔作為程式碼替代,而不是程式碼中冗長的$f3->set()語句。我們將上面的文字儲存為 setup.cfg。然後我們可以用一個簡單的方式來呼叫它:-
$ f3 -> config ( ' setup.cfg ' );字串值不需要加引號,除非您希望包含前導或尾隨空格。如果逗號應被視為字串的一部分,請使用雙引號將字串括起來 - 否則,該值將被視為陣列(逗號用作陣列元素分隔符號)。字串可以跨越多行:-
[globals]
str = " this is a
very long
string "F3 還可讓您在設定檔中定義 HTTP 路由:-
[routes]
GET /=home
GET / 404 =App->page404
GET /page/@ num =Page->@controller路由映射也可以在設定檔中定義:-
[maps]
/ blog =BlogLogin
/blog/@ controller =Blog@controller [globals] 、 [routes]和[maps]節標題是必需的。您可以將這兩個部分合併在一個設定檔中 - 儘管建議將[routes]和[maps]放在單獨的檔案中。透過這種方式,您可以允許最終用戶修改一些特定於應用程式的標誌,同時限制他們幹擾您的路由邏輯。
像 HTML 頁面這樣的使用者介面應該獨立於與路由和業務邏輯相關的底層 PHP 程式碼。這是 MVC 範例的基礎。像將<h3>轉換為<p>這樣的基本修訂不應要求更改應用程式程式碼。同樣,將GET /about等簡單路由轉換為GET /about-us不應對您的使用者介面和業務邏輯(MVC 中的視圖和模型,或 RMR 中的表示和方法)產生任何影響。
將程式設計結構和使用者介面元件混合在一個檔案中,就像義大利麵條編碼一樣,使未來的應用程式維護成為一場噩夢。
F3 支援 PHP 作為模板引擎。看一下這個保存為template.htm HTML 片段:-。
< p > Hello, < ?php echo $name; ? > ! </ p >如果您的伺服器上啟用了短標籤,這也應該有效:-
< p > Hello, < ?= $name ? > </ p >要顯示此模板,您可以使用如下所示的 PHP 程式碼(儲存在與模板分開的檔案中):-
$ f3 = require ( ' lib/base.php ' );
$ f3 -> route ( ' GET / ' ,
function ( $ f3 ) {
$ f3 -> set ( ' name ' , ' world ' );
$ view = new View ;
echo $ view -> render ( ' template.htm ' );
// Previous two lines can be shortened to : -
// echo View :: instance () - > render ( 'template.htm' );
}
);
$ f3 -> run ();由於這些文件中嵌入了 PHP 程式碼,使用 PHP 作為模板引擎的唯一問題是需要有意識地努力遵守關注點分離的準則,並抵制將業務邏輯與使用者介面混合的誘惑。
作為 PHP 的替代方案,您可以使用 F3 自己的模板引擎。上面的 HTML 片段可以改寫為:-
< p > Hello, {{ @name }}! </ p >以及查看此模板所需的程式碼:-
$ f3 = require ( ' lib/base.php ' );
$ f3 -> route ( ' GET / ' ,
function ( $ f3 ) {
$ f3 -> set ( ' name ' , ' world ' );
$ template = new Template ;
echo $ template -> render ( ' template.htm ' );
// Above lines can be written as : -
// echo Template :: instance () - > render ( 'template.htm' );
}
);
$ f3 -> run ();與用於捕獲 URL 中的變數的路由標記一樣(還記得上一節中的GET /brew/@count範例嗎?),F3 範本標記以@符號開頭,後面跟著一系列用大括號括起來的字母和數字。第一個字元必須是字母。模板標記與框架變數具有一一對應的關係。框架會自動將標記替換為儲存在同名變數中的值。
在我們的範例中,F3 將範本中的@name標記替換為我們指派給 name 變數的值。在運行時,上述程式碼的輸出將是:-
< p > Hello, world </ p >擔心 F3 模板的效能?在執行時,框架會在首次透過$template->render()顯示 F3 模板時解析並編譯/轉換為 PHP 程式碼。然後,框架在所有後續呼叫中使用此編譯的程式碼。因此,當涉及更複雜的模板時,由於模板編譯器所做的程式碼最佳化,效能即使不是更好,也應該與 PHP 模板相同。
無論您使用 PHP 的模板引擎還是 F3 自己的模板引擎,如果您的伺服器上有 APC、WinCache 或 XCache,模板渲染都會顯著加快。
如前所述,框架變數可以保存任何 PHP 資料類型。但是,如果您不小心,在 F3 範本中使用非標量資料類型可能會產生奇怪的結果。大括號中的表達式將始終被計算並轉換為字串。您應該將使用者介面變數限制為簡單的標量: string 、 integer 、 boolean或float資料類型。
但是數組呢? Fat-Free 可以識別數組,您可以在範本中使用它們。你可以有這樣的東西:-
< p > {{ @buddy[0] }}, {{ @buddy[1] }}, and {{ @buddy[2] }} </ p >並在提供模板之前在 PHP 程式碼中填充@buddy數組:-
$ f3 -> set ( ' buddy ' ,[ ' Tom ' , ' Dick ' , ' Harry ' ]);但是,如果您只是在模板中插入{{ @buddy }} ,PHP 會將其替換為'Array'因為它將標記轉換為字串。另一方面,PHP 將在運行時產生Array to string conversion通知。
F3 允許您在模板中嵌入表達式。這些表達式可以採用各種形式,例如算術計算、布林表達式、PHP 常數等。
{{ 2*(@page-1) }}
{{ (int)765.29+1.2e3 }}
< option value =" F " {{ @active? 'selected=" selected "':'' }} > Female </ option >
{{ var_dump(@xyz) }}
< p > That is {{ preg_match('/Yes/i',@response)?'correct':'wrong' }}! </ p >
{{ @obj- > property }}關於陣列表達式的附加說明:請注意@foo.@bar是字串連接$foo.$bar ),而@foo.bar轉換為$foo['bar'] 。如果$foo[$bar]是您想要的,請使用@foo[@bar]常規符號。
框架變數也可能包含匿名函數:
$ f3 -> set ( ' func ' ,
function ( $ a , $ b ) {
return $ a . ' , ' . $ b ;
}
);如果您指定以下表達式,F3 模板引擎將如預期解釋令牌:
{{ @func('hello','world') }}簡單的變數替換是所有模板引擎都具備的一件事。 Fat-Free 還有更多優點:-
< include href =" header.htm " />該指令會將 header.htm 範本的內容嵌入到該指令所宣告的確切位置。您還可以擁有以下形式的動態內容:-
< include href =" {{ @content }} " />這種模板指令的實際用途是當您有多個具有共同 HTML 佈局但內容不同的頁面時。指示框架將子模板插入到主模板就像編寫以下 PHP 程式碼一樣簡單:-
// switch content to your blog sub - template
$ f3 -> set ( ' content ' , ' blog.htm ' );
// in another route , switch content to the wiki sub - template
$ f3 -> set ( ' content ' , ' wiki.htm ' );子模板又可以包含任意數量的指令。 F3 允許無限嵌套模板。
您可以使用 .htm 或 .html 檔案副檔名以外的檔案名稱來指定檔案名,但在開發和偵錯階段在 Web 瀏覽器中預覽它們會更容易。模板引擎不僅限於渲染 HTML 檔案。事實上,您可以使用模板引擎來渲染其他類型的檔案。
<include>指令還有一個可選的if屬性,因此您可以指定插入子模板之前需要滿足的條件:-
< include if =" {{ count(@items) }} " href =" items.htm " />在編寫/調試 F3 支援的程式和設計模板的過程中,有時可能會很方便地停用 HTML 區塊的顯示。您可以使用<exclude>指令來達到此目的:-
< exclude >
< p > A chunk of HTML we don't want displayed at the moment </ p >
</ exclude >這就像<!-- comment --> HTML 註解標記,但是<exclude>指令使 HTML 區塊在模板渲染後完全不可見。
這是排除模板內容或添加註釋的另一種方法:-
{* < p > A chunk of HTML we don't want displayed at the moment </ p > *}另一個有用的範本功能是<check>指令。它允許您根據特定條件的評估嵌入 HTML 片段。以下是一些例子:-
< check if =" {{ @page=='Home' }} " >
< false > < span > Inserted if condition is false </ span > </ false >
</ check >
< check if =" {{ @gender=='M' }} " >
< true >
< div > Appears when condition is true </ div >
</ true >
< false >
< div > Appears when condition is false </ div >
</ false >
</ check >您可以根據需要擁有任意數量的巢狀<check>指令。
if 屬性內的 F3 表達式等於NULL 、空字串、布林值FALSE 、空數組或零,自動呼叫<false> 。如果您的範本沒有<false>區塊,則<true>開始和結束標記是可選的:-
< check if =" {{ @loggedin }} " >
< p > HTML chunk to be included if condition is true </ p >
</ check >Fat-Free 也可以處理重複的 HTML 區塊:-
< repeat group =" {{ @fruits }} " value =" {{ @fruit }} " >
< p > {{ trim(@fruit) }} </ p >
</ repeat > <repeat>指令內的group屬性@fruits必須是一個數組,並且應在 PHP 程式碼中進行相應設定:-
$ f3 -> set ( ' fruits ' ,[ ' apple ' , ' orange ' , ' banana ' ]);在應用程式程式碼中為@fruit賦值不會帶來任何好處。 Fat-Free 忽略它可能具有的任何預設值,因為它在群組迭代期間使用變數來表示當前專案。上述 HTML 模板片段和對應的 PHP 程式碼的輸出變成:-
< p > apple </ p >
< p > orange </ p >
< p > banana </ p >該框架允許無限嵌套<repeat>塊:-
< repeat group =" {{ @div }} " key =" {{ @ikey }} " value =" {{ @idiv }} " >
< div >
< p > < span > < b > {{ @ikey }} </ b > </ span > </ p >
< p >
< repeat group =" {{ @idiv }} " value =" {{ @ispan }} " >
< span > {{ @ispan }} </ span >
</ repeat >
</ p >
</ div >
</ repeat >應用以下 F3 指令:-
$ f3 -> set ( ' div ' ,
[
' coffee ' =>[ ' arabica ' , ' barako ' , ' liberica ' , ' kopiluwak ' ],
' tea ' =>[ ' darjeeling ' , ' pekoe ' , ' samovar ' ]
]
);結果,您將獲得以下 HTML 片段:-
< div >
< p > < span > < b > coffee </ b > </ span > </ p >
< p >
< span > arabica </ span >
< span > barako </ span >
< span > liberica </ span >
< span > kopiluwak </ span >
< p >
</ div >
< div >
< p > < span > < b > tea </ b > </ span > </ p >
< p >
< span > darjeeling </ span >
< span > pekoe </ span >
< span > samovar </ span >
</ p >
</ div >太棒了,不是嗎?在 PHP 中您唯一需要做的就是定義單一 F3 變數div的內容來替換@div標記。 Fat-Free 讓程式設計和 Web 範本設計變得非常簡單。
<repeat>範本指令的value屬性傳回迭代中目前元素的值。如果需要取得目前元素的陣列鍵,請使用key屬性。 key屬性是可選的。
<repeat>還有一個可選的計數器屬性,可以如下使用:-
< repeat group =" {{ @fruits }} " value =" {{ @fruit }} " counter =" {{ @ctr }} " >
< p class =" {{ @ctr%2?'odd':'even' }} " > {{ trim(@fruit) }} </ p >
</ repeat >在內部,F3 的範本引擎記錄循環迭代的次數,並將該值保存在變數/標記@ctr中,該值在我們的範例中用於確定奇數/偶數分類。
如果您必須在模板的<script>或<style>部分中插入 F3 標記,框架仍將以通常的方式替換它們:-
< script type =" text/javascript " >
function notify ( ) {
alert ( 'You are logged in as: {{ @userID }}' ) ;
}
</ script >在<script>或<style>標記中嵌入模板指令不需要特殊處理:-
< script type =" text/javascript " >
var discounts = [ ] ;
< repeat group = "{{ @rates }}" value = "{{ @rate }}" >
// whatever you want to repeat in Javascript, e.g.
discounts.push(" { { @ rate } } ");
</ repeat >
</ script >預設情況下,除非進行更改,Fat-Free 使用 UTF-8 字元集。您可以透過發出以下命令來覆寫此行為:-
$ f3 -> set ( ' ENCODING ' , ' ISO-8859-1 ' );一旦您告知框架所需的字元集,F3 將在所有 HTML 和 XML 模板中使用它,直到再次變更。
如本節前面所提到的,該框架不僅限於 HTML 範本。您也可以處理 XML 模板。機制非常相似。您仍然可以使用相同的{{ @variable }}和{{ expression }}標記、 <repeat> 、 <check> 、 <include>和<exclude>指令。只需告訴 F3 您正在傳遞 XML 檔案而不是 HTML:-
echo Template:: instance ()-> render ( ' template.xml ' , ' application/xml ' );第二個參數表示正在呈現的文件的 MIME 類型。
MVC 的視圖元件涵蓋了模型和控制器之外的所有內容,這意味著您的簡報可以而且應該包含所有類型的使用者介面,例如 RSS、電子郵件、RDF、FOAF、文字檔案等。展示如何將電子郵件簡報與應用程式的業務邏輯分開:-
MIME-Version: 1.0
Content-type: text/html; charset={{ @ENCODING }}
From: {{ @from }}
To: {{ @to }}
Subject: {{ @subject }}
< p > Welcome, and thanks for joining {{ @site }}! </ p >將以上電子郵件範本另存為welcome.txt。相關的 F3 代碼為:-
$ f3 -> set ( ' from ' , ' <[email protected]> ' );
$ f3 -> set ( ' to ' , ' <[email protected]> ' );
$ f3 -> set ( ' subject ' , ' Welcome ' );
ini_set ( ' sendmail_from ' , $ f3 -> get ( ' from ' ));
mail (
$ f3 -> get ( ' to ' ),
$ f3 -> get ( ' subject ' ),
Template:: instance ()-> render ( ' email.txt ' , ' text/html ' )
);提示:如果您的腳本與 IMAP 伺服器通信,請將 SMTP mail() 函數替換為 imap_mail()。
現在那不是嗎?當然,如果您有一組電子郵件收件人,您將使用資料庫來填入姓名、姓氏和電子郵件標記。
這是使用 F3 的 SMTP 插件的替代解決方案:-
$ mail = new SMTP ( ' smtp.gmail.com ' , 465 , ' SSL ' , ' [email protected] ' , ' secret ' );
$ mail -> set ( ' from ' , ' <[email protected]> ' );
$ mail -> set ( ' to ' , ' "Slasher" <[email protected]> ' );
$ mail -> set ( ' subject ' , ' Welcome ' );
$ mail -> send (Template:: instance ()-> render ( ' email.txt ' ));F3 開箱即用,支援多種語言。
首先,建立一個具有以下結構的字典檔案(每種語言一個檔案):-
<?php
return [
' love ' => ' I love F3 ' ,
' today ' => ' Today is {0,date} ' ,
' pi ' => ' {0,number} ' ,
' money ' => ' Amount remaining: {0,number,currency} '
];將其另存為dict/en.php 。讓我們創建另一個字典,這次是德語字典。將檔案另存為dict/de.php :-
<?php
return [
' love ' => ' Ich liebe F3 ' ,
' today ' => ' Heute ist {0,date} ' ,
' money ' => ' Restbetrag: {0,number,currency} '
];字典只不過是鍵值對。 F3 根據語言檔案中的鍵自動實例化框架變數。因此,可以輕鬆地將這些變數作為標記嵌入到模板中。使用 F3 模板引擎:-
< h1 > {{ @love }} </ h1 >
< p >
{{ @today,time() | format }}. < br />
{{ @money,365.25 | format }} < br />
{{ @pi }}
</ p >更長的版本使用 PHP 作為模板引擎:-
<?php $ f3 =Base:: instance (); ?>
<h1> <?php echo $ f3 -> get ( ' love ' ); ?> </h1>
<p>
<?php echo $ f3 -> get ( ' today ' , time ()); ?> .<br />
<?php echo $ f3 -> get ( ' money ' , 365.25 ); ?>
<?php echo $ f3 -> get ( ' pi ' ); ?>
</p>接下來,我們指示 F3 在dict/資料夾中尋找字典:-
$ f3 -> set ( ' LOCALES ' , ' dict/ ' );但是框架如何決定要使用哪種語言呢? F3 將首先查看 HTTP 請求標頭(特別是瀏覽器發送的Accept-Language標頭)來自動偵測它。
若要覆寫此行為,您可以觸發 F3 使用使用者或應用程式指定的語言:-
$ f3 -> set ( ' LANGUAGE ' , ' de ' );注意:在上面的例子中,鍵 pi 僅存在於英語字典中。此框架將始終使用英語 ( en ) 作為後備來填充指定(或檢測到的)語言中不存在的鍵。
您也可以為en-US 、 es-AR es-AR語言變體建立字典檔案。如果變體中不存在鍵,框架將在根語言( es )中尋找鍵,然後使用en語言檔案作為最終後備。字典鍵值對一旦被引用就成為F3變數。確保這些鍵不會與任何透過$f3->set() 、 $f3->mset()或$f3->config()實例化的框架變數衝突。
您是否注意到我們前面的範例中特殊的'Today is {0,date}'模式? F3 的多語言能力取決於 ICU 項目的字串/訊息格式規則。該框架使用自己的 ICU 字串格式化實作子集。無需在伺服器上啟動 PHP 的intl擴充。
還有一件事:F3 還可以載入 .ini 樣式格式的檔案作為字典:-
love = " I love F3 "
today = " Today is {0,date} "
pi = " {0,number} "
money = " Amount remaining: {0,number,currency} "將其儲存為dict/en.ini以便框架可以自動載入它。
預設情況下,視圖處理程序和範本引擎都會轉義所有呈現的變量,即轉換為 HTML 實體,以保護您免受可能的 XSS 和程式碼注入攻擊。另一方面,如果您希望將有效的 HTML 片段從應用程式程式碼傳遞到模板:-
$ f3 -> set ( ' ESCAPE ' , FALSE );這可能會產生不良影響。您可能不希望所有變數都以未轉義的方式傳遞。 Fat-Free 讓您單獨取消轉義變數。對於 F3 模板:-
{{ @html_content | raw }}對於 PHP 模板:-
<?php echo View:: instance ()-> raw ( $ html_content ); ?>作為 F3 變數自動轉義的補充,該框架還使您可以自由地清理 HTML 表單中的使用者輸入:-
$ f3 -> scrub ( $ _GET , ' p; br; span; div; a ' );此命令將從指定變數中刪除所有標記(第二個參數中指定的標記除外)和不安全字元。如果變數包含數組,則數組中的每個元素都會被遞歸地清理。如果星號 (*) 作為第二個參數傳遞, $f3->scrub()允許所有 HTML 標記不受影響地通過,並且僅刪除不安全的控製字元。
Fat-Free 旨在讓與 SQL 資料庫的連線工作變得輕而易舉。如果您不是那種沉浸在 SQL 細節中的人,而是更傾向於物件導向的資料處理,那麼您可以直接進入本教學的下一部分。但是,如果您需要執行一些複雜的資料處理和資料庫效能最佳化任務,那麼 SQL 是最佳選擇。
使用熟悉的$f3->set()指令與 MySQL、SQLite、SQL Server、Sybase 和 Oracle 等 SQL 引擎建立通訊。連接到 SQLite 資料庫將是:-
$ db = new DB SQL ( ' sqlite:/absolute/path/to/your/database.sqlite ' );另一個例子,這次是 MySQL:-
$ db = new DB SQL (
' mysql:host=localhost;port=3306;dbname=mysqldb ' ,
' admin ' ,
' p455w0rD '
);好的。那很容易,不是嗎?這幾乎就是您在普通 PHP 中執行相同操作的方式。您只需要知道要連接的資料庫的 DSN 格式。請參閱 PHP 手冊的 PDO 部分。
讓我們繼續我們的 PHP 程式碼:-
$ f3 -> set ( ' result ' , $ db -> exec ( ' SELECT brandName FROM wherever ' ));
echo Template:: instance ()-> render ( ' abc.htm ' );呃,這是怎麼回事?難道我們不應該設定 PDO、語句、遊標等東西嗎?簡單的答案是:你不必這樣做。 F3 透過處理後端的所有艱苦工作來簡化一切。
這次我們建立一個像abc.htm這樣的 HTML 模板,它至少有以下內容:-
< repeat group =" {{ @result }} " value =" {{ @item }} " >
< span > {{ @item.brandName }} </ span >
</ repeat >在大多數情況下,SQL 命令集應該足以產生 Web 就緒的結果,以便您可以直接在範本中使用result陣列變數。儘管如此,Fat-Free 不會阻止您了解其 SQL 處理程序的內部結構。事實上,F3 的DBSQL類別直接衍生自 PHP 的PDO類,因此如果您需要一些細粒度的控制,您仍然可以存取每個過程中涉及的底層 PDO 元件和原語。
這是另一個例子。您也可以傳遞 SQL 語句數組,而不是作為參數提供給$db->exec()命令的單一語句:-
$ db -> exec (
[
' DELETE FROM diet WHERE food="cola" ' ,
' INSERT INTO diet (food) VALUES ("carrot") ' ,
' SELECT * FROM diet '
]
);F3 夠聰明,知道如果您傳遞一組 SQL 指令,則表示這是 SQL 批次交易。您不必擔心 SQL 回滾和提交,因為如果交易期間發生任何錯誤,框架將自動還原到資料庫的初始狀態。如果成功,F3 將提交對資料庫所做的所有變更。
您也可以以程式設計方式開始和結束事務:-
$ db -> begin ();
$ db -> exec ( ' DELETE FROM diet WHERE food="cola" ' );
$ db -> exec ( ' INSERT INTO diet (food) VALUES ("carrot") ' );
$ db -> exec ( ' SELECT * FROM diet ' );
$ db -> commit ();如果任何語句遇到錯誤,就會發生回溯。
要取得所有發出的資料庫指令的清單:-
echo $ db -> log ();將字串參數傳遞給 SQL 語句充滿了危險。考慮一下:-
$ db -> exec (
' SELECT * FROM users ' .
' WHERE username=" ' . $ f3 -> get ( ' POST.userID ' . ' " ' )
);如果POST變數userID未經過任何資料清理過程,則惡意使用者可以傳遞以下字串並不可逆轉地損壞您的資料庫:-
admin " ; DELETE FROM users; SELECT " 1幸運的是,參數化查詢可以幫助您減輕這些風險:-
$ db -> exec (
' SELECT * FROM users WHERE userID=? ' ,
$ f3 -> get ( ' POST.userID ' )
);如果 F3 偵測到查詢參數/令牌的值是字串,則底層資料存取層會對字串進行轉義並根據需要新增引號。
如果這樣寫,我們上一節的範例將更安全,不會受到 SQL 注入的影響:-
$ db -> exec (
[
' DELETE FROM diet WHERE food=:name ' ,
' INSERT INTO diet (food) VALUES (?) ' ,
' SELECT * FROM diet '
],
[
array ( ' :name ' => ' cola ' ),
array ( 1 => ' carrot ' ),
NULL
]
);F3 包含易於使用的物件關聯映射器 (ORM),它們位於您的應用程式和資料之間 - 讓您更輕鬆、更快速地編寫處理常見資料操作的程式 - 例如建立、檢索、更新、從SQL和NoSQL 資料庫中刪除(CRUD) 資訊。資料映射器透過將 PHP 物件互動映射到對應的後端查詢來完成大部分工作。
假設您有一個現有的 MySQL 資料庫,其中包含應用程式的使用者表。 (SQLite、PostgreSQL、SQL Server、Sybase 也可以。)它可以使用下列 SQL 指令建立:-
CREATE TABLE users (
userID VARCHAR ( 30 ),
password VARCHAR ( 30 ),
visits INT ,
PRIMARY KEY (userID)
);注意: MongoDB 是一個 NoSQL 資料庫引擎,本質上是無模式的。 F3 有自己的快速且輕量級的 NoSQL 實現,稱為 Jig,它使用 PHP 序列化或 JSON 編碼的平面檔案。這些抽象層不需要嚴格的資料結構。欄位可能因一筆記錄而異。它們也可以動態定義或刪除。
現在回到 SQL。首先,我們與資料庫建立通訊。
$ db = new DB SQL (
' mysql:host=localhost;port=3306;dbname=mysqldb ' ,
' admin ' ,
' wh4t3v3r '
);要從我們的表中檢索記錄:-
$ user = new DB SQL Mapper ( $ db , ' users ' );
$ user -> load ([ ' userID=? ' , ' tarzan ' ]);第一行實例化一個與資料庫中的users表互動的資料映射器物件。在幕後,F3 檢索users表的結構並確定哪些欄位被定義為主鍵。此時,映射器物件尚不包含任何資料(乾狀態),因此$user只不過是一個結構化物件 - 但它包含執行基本 CRUD 操作和一些額外操作所需的方法。要從使用者表中檢索包含字串值tarzan的userID欄位的記錄,我們使用load() method 。此過程稱為“自動水化”資料映射器物件。
很容易,不是嗎? F3 知道 SQL 表已經在資料庫引擎本身中存在結構定義。與其他框架不同,F3 不需要額外的類別聲明(除非您想要擴展資料映射器以適應複雜的物件),不需要冗餘的PHP 陣列/物件屬性到欄位的映射(重複工作),不需要程式碼生成器(需要程式碼)如果資料庫結構發生變化,則重新產生),沒有愚蠢的 XML/YAML 檔案來配置模型,沒有多餘的命令來檢索單一記錄。使用 F3,簡單地調整 MySQL 中varchar欄位的大小不需要更改應用程式程式碼。與 MVC 和「關注點分離」一致,資料庫管理員對資料(和結構)的控制與模板設計者對 HTML/XML 模板的控制一樣多。
如果您喜歡使用 NoSQL 資料庫,那麼查詢語法的相似之處只是表面的。對於 MongoDB 資料映射器,等效代碼是:-
$ db = new DB Mongo ( ' mongodb://localhost:27017 ' , ' testdb ' );
$ user = new DB Mongo Mapper ( $ db , ' users ' );
$ user -> load ([ ' userID ' => ' tarzan ' ]);使用 Jig,語法類似 F3 的模板引擎:-
$ db = new DB Jig ( ' db/data/ ' , DB Jig:: FORMAT_JSON );
$ user = new DB Jig Mapper ( $ db , ' users ' );
$ user -> load ([ ' @userID=? ' , ' tarzan ' ]);在物件實例化期間,框架會自動將表格中的欄位visits對應到資料映射器屬性,即$user=new DBSQLMapper($db,'users'); 。建立物件後, $user->password和$user->userID將分別對應到表格中的password和userID欄位。
您無法新增或刪除映射字段,也無法使用 ORM 變更表的結構。您必須在 MySQL 或您使用的任何資料庫引擎中執行此操作。在資料庫引擎中進行變更後,當您執行應用程式時,Fat-Free 將自動將新的表結構與資料映射器物件同步。
F3 直接從資料庫模式匯出資料映射器結構。不涉及猜測。它了解 MySQL、SQLite、MSSQL、Sybase 和 PostgreSQL 資料庫引擎之間的差異。
SQL 識別碼不應使用保留字,並且應限制為字母數字字元AZ 、 0-9和底線符號 ( _ )。資料定義中包含空格(或特殊字元)並以引號引起來的列名與 ORM 不相容。它們無法正確表示為 PHP 物件屬性。
假設我們想要增加用戶的訪問次數並更新用戶表中的相應記錄,我們可以添加以下代碼:-
$ user -> visits ++;
$ user -> save ();如果我們想要插入一筆記錄,我們遵循以下流程:-
$ user = new DB SQL Mapper ( $ db , ' users ' );
// or $ user = new DB Mongo Mapper ($ db , 'users' );
// or $ user = new DB Jig Mapper ($ db , 'users' );
$ user -> userID = ' jane ' ;
$ user -> password = password_hash ( ' secret ' , PASSWORD_BCRYPT , [ ' cost ' => 12 ]);
$ user -> visits = 0 ;
$ user -> save ();我們仍然使用相同的save()方法。但是 F3 如何知道何時應該插入或更新記錄?當資料映射器物件透過記錄檢索自動水合時,框架會追蹤記錄的主鍵(或_id ,在 MongoDB 和 Jig 的情況下) - 因此它知道應該更新或刪除哪個記錄 - 甚至當主鍵的值改變時。以程式設計方式水合的資料映射器(其值不是從資料庫檢索的,而是由應用程式填充的)在其主鍵中不會有任何先前值的記憶體。這同樣適用於 MongoDB 和 Jig,但使用 object _id作為參考。因此,當我們實例化上面的$user物件並使用程式中的值填充其屬性時 - 根本不需要從使用者表中檢索記錄,F3 就知道它應該插入該記錄。
save()之後映射器物件不會為空。如果您希望在資料庫中新增記錄,則必須先對映射器進行脫水:-
$ user -> reset ();
$ user -> userID = ' cheetah ' ;
$ user -> password = password_hash ( ' unknown ' , PASSWORD_BCRYPT , [ ' cost ' => 12 ]);
$ user -> save ();再次呼叫save()而不呼叫reset()將簡單地更新映射器目前指向的記錄。
儘管資料庫中所有表都具有主鍵的問題存在爭議,但 F3 不會阻止您建立與不包含主鍵的表進行通訊的資料映射器物件。唯一的缺點是:您無法刪除或更新映射記錄,因為 F3 絕對無法確定您所引用的記錄,而且位置引用不可靠。行 ID 不可跨不同 SQL 引擎移植,且 PHP 資料庫驅動程式可能不會傳回。
若要從表格中刪除映射記錄,請在自動水合資料映射器上呼叫erase()方法。例如:-
$ user = new DB SQL Mapper ( $ db , ' users ' );
$ user -> load ([ ' userID=? AND password=? ' , ' cheetah ' , ' ch1mp ' ]);
$ user -> erase ();Jig 的查詢語法有點相似:-
$ user = new DB Jig Mapper ( $ db , ' users ' );
$ user -> load ([ ' @userID=? AND @password=? ' , ' cheetah ' , ' chimp ' ]);
$ user -> erase ();MongoDB 的等價物是:-
$ user = new DB Mongo Mapper ( $ db , ' users ' );
$ user -> load ([ ' userID ' => ' cheetah ' , ' password ' => ' chimp ' ]);
$ user -> erase ();要查明我們的資料映射器是否水合:-
if ( $ user -> dry ())
echo ' No record matching criteria ' ;我們已經介紹了 CRUD 處理程序。您可能會發現一些有用的額外方法:-
$ f3 -> set ( ' user ' , new DB SQL Mapper ( $ db , ' users ' ));
$ f3 -> get ( ' user ' )-> copyFrom ( ' POST ' );
$ f3 -> get ( ' user ' )-> save ();請注意,我們也可以使用 Fat-Free 變數作為映射器物件的容器。 copyFrom()方法使用框架數組變數中的元素來填充映射器對象,該數組變數的數組鍵必須具有與映射器對象屬性相同的名稱,而映射器對象屬性又對應於記錄的字段名稱。因此,當提交 Web 表單時(假設 HTML 名稱屬性設定為userID ),該輸入欄位的內容將傳輸到$_POST['userID'] ,透過 F3 在其POST.userID變數中複製,並儲存到資料庫中的映射欄位$user->userID 。如果它們都具有相同名稱的元素,則該過程將變得非常簡單。數組鍵(即模板標記名稱、框架變數名稱和欄位名稱)的一致性是關鍵:)
另一方面,如果我們想要檢索記錄並將欄位值複製到框架變數以供以後使用,例如範本渲染:-
$ f3 -> set ( ' user ' , new DB SQL Mapper ( $ db , ' users ' ));
$ f3 -> get ( ' user ' )-> load ([ ' userID=? ' , ' jane ' ]);
$ f3 -> get ( ' user ' )-> copyTo ( ' POST ' );然後我們可以將 {{ @POST.userID }} 指派給同一輸入欄位的 value 屬性。總而言之,HTML 輸入欄位將如下所示:-
< input type =" text " name =" userID " value =" {{ @POST.userID }} " /> save() 、 update() 、 copyFrom()資料映射器方法以及load()和erase()的參數化變體對於 SQL 注入是安全的。
預設情況下,資料映射器的load()方法僅會擷取與指定條件相符的第一筆記錄。如果您有多個符合與載入的第一筆記錄相同的條件,則可以使用skip()方法進行導覽:-
$ user = new DB SQL Mapper ( $ db , ' users ' );
$ user -> load ( ' visits>3 ' );
// Rewritten as a parameterized query
$ user -> load ([ ' visits>? ' , 3 ]);
// For MongoDB users : -
// $ user = new DB Mongo Mapper ($ db , 'users' );
// $ user - > load ([ 'visits' = > [ '$gt' = > 3 ]]);
// If you prefer Jig : -
// $ user = new DB Jig Mapper ($ db , 'users' );
// $ user - > load ( '@visits>?' , 3 );
// Display the userID of the first record that matches the criteria
echo $ user -> userID ;
// Go to the next record that matches the same criteria
$ user -> skip (); // Same as $ user - > skip ( 1 );
// Back to the first record
$ user -> skip (- 1 );
// Move three records forward
$ user -> skip ( 3 );您可以使用$user->next()來取代$user->skip()和$user->prev()如果您認為它賦予$user->skip(-1)更多意義。
使用dry()方法檢查是否超出了結果集的限制。如果您在第一筆記錄上嘗試使用skip(-1) dry()將傳回TRUE。如果您在滿足檢索條件的最後一筆記錄上skip(1)它也會傳回 TRUE。
load()方法接受第二個參數:包含鍵值對的選項數組,例如:-
$ user -> load (
[ ' visits>? ' , 3 ],
[
' order ' => ' userID DESC '
'offset'=> 5 ,
' limit ' => 3
]
);如果您使用 MySQL,則查詢將轉換為:-
SELECT * FROM users
WHERE visits > 3
ORDER BY userID DESC
LIMIT 3 OFFSET 5 ;這是以小塊形式呈現資料的一種方式。這是另一種對結果進行分頁的方法:-
$ page = $ user -> paginate ( 2 , 5 ,[ ' visits>? ' , 3 ]);在上述情境中,F3 將擷取符合條件'visits>3'的記錄。然後,它將結果限制為從頁偏移 2(從 0 開始)開始的 5 筆記錄(每頁)。該框架將傳回一個由以下元素組成的陣列:-
[subset] array of mapper objects that match the criteria
[count] number of subsets available
[pos] actual subset position
如果paginate()的第一個參數是負數或超過找到的子集數量,則傳回的實際子集位置將為 NULL。
在某些情況下,您需要檢索欄位的計算值或來自另一個表的交叉引用值。輸入虛擬欄位。 SQL mini-ORM 可讓您處理從現有欄位派生的資料。
假設我們將下表定義為:-
CREATE TABLE products
productID VARCHAR ( 30 ),
description VARCHAR ( 255 ),
supplierID VARCHAR ( 30 ),
unitprice DECIMAL ( 10 , 2 ),
quantity INT ,
PRIMARY KEY (productID)
);不存在totalprice字段,因此我們可以告訴框架向資料庫引擎請求這兩個字段的算術乘積:-
$ item = new DB SQL Mapper ( $ db , ' products ' );
$ item -> totalprice = ' unitprice*quantity ' ;
$ item -> load ([ ' productID=:pid ' , ' :pid ' => ' apple ' ]);
echo $ item -> totalprice ;上面的程式碼片段定義了一個名為totalprice的虛擬字段,它是透過將unitprice乘以quantity來計算的。 SQL 映射器保存該規則/公式,因此當需要從資料庫檢索記錄時,我們可以像常規映射欄位一樣使用虛擬欄位。
您可以擁有更複雜的虛擬欄位:-
$ item -> mostNumber = ' MAX(quantity) ' ;
$ item -> load ();
echo $ item -> mostNumber ;這次框架檢索數量最多的產品(請注意load()方法沒有定義任何條件,因此將處理表中的所有記錄)。當然,如果您希望將表達式限制為與指定條件相符的特定記錄組,則虛擬欄位mostNumber仍將為您提供正確的數字。
您也可以從另一個表中取得值:-
$ item -> supplierName =
' SELECT name FROM suppliers ' .
' WHERE products.supplierID=suppliers.supplierID ' ;
$ item -> load ();
echo $ item -> supplierName ;每次從產品表載入記錄時,ORM 都會交叉引用products表中的supplerID與suppliers表中的supplierID 。
要銷毀虛擬字段,請使用unset($item->totalPrice); 。如果定義了totalPrice虛擬字段,則isset($item->totalPrice)表達式傳回 TRUE,否則傳回 FALSE。
請記住,必須在資料檢索之前定義虛擬欄位。 ORM 不會執行實際計算,也不從另一個表格匯出結果。資料庫引擎完成了所有艱苦的工作。
如果您不需要逐筆記錄導航,您可以一次檢索整批記錄:-
$ frequentUsers = $ user -> find ([ ' visits>? ' , 3 ],[ ' order ' => ' userID ' ]);Jig 映射器的查詢語法略有相似:-
$ frequentUsers = $ user -> find ([ ' @visits>? ' , 3 ],[ ' order ' => ' userID ' ]);使用 MongoDB 映射器的等效程式碼:-
$ frequentUsers = $ user -> find ([ ' visits ' =>[ ' $gt ' => 3 ]],[ ' userID ' => 1 ]); find()方法在users表中搜尋符合條件的記錄,按userID對結果進行排序,並將結果作為映射器物件陣列傳回。 find('visits>3')與load('visits>3')不同。後者引用目前的$user物件。 find()對skip()沒有任何影響。
重要提示:宣告空條件、NULL 或零長度字串作為find()或load()的第一個參數將檢索所有記錄。確保您知道自己在做什麼 - 您可能會超出 PHP 在大型表或集合上的記憶體限制。
find()方法有以下語法:-
find (
$ criteria ,
[
' group ' => ' foo ' ,
' order ' => ' foo,bar ' ,
' limit ' => 5 ,
' offset ' => 0
]
);find() 傳回一個物件數組。每個物件都是與指定條件相符的記錄的映射器。
$ place = new DB SQL Mapper ( $ db , ' places ' );
$ list = $ place -> find ( ' state="New York" ' );
foreach ( $ list as $ obj )
echo $ obj -> city . ' , ' . $ obj -> country ;如果需要將映射器物件轉換為關聯數組,請使用cast()方法:-
$ array = $ place -> cast ();
echo $ array [ ' city ' ]. ' , ' . $ array [ ' country ' ];若要檢索表格中符合特定條件的記錄數,請使用count()方法。
if (! $ user -> count ([ ' visits>? ' , 10 ]))
echo ' We need a better ad campaign! ' ;還有一個select()方法,與find()類似,但對傳回的欄位提供更細粒度的控制。它有類似 SQL 的語法:-
select (
' foo, bar, MIN(baz) AS lowest ' ,
' foo > ? ' ,
[
' group ' => ' foo, bar ' ,
' order ' => ' baz ASC ' ,
' limit ' => 5 ,
' offset ' => 3
]
);與find()方法非常相似, select()不會更改映射器物件的內容。它僅作為查詢映射表的便捷方法。這兩個方法的回傳值都是映射器物件的陣列。使用dry()來確定是否透過這些方法找到記錄是不合適的。如果沒有記錄符合find()或select()標準,則傳回值為空數組。
如果您想找出應用程式直接發出的哪些 SQL 語句(或透過映射器物件間接發出的)導致效能瓶頸,您可以透過以下簡單操作來實現:
echo $ db -> log ();F3 追蹤向底層 SQL 資料庫驅動程式發出的所有命令,以及完成每個語句所需的時間 - 這正是您調整應用程式效能所需的正確資訊。
在大多數情況下,您可以享受我們迄今為止討論的數據映射器方法所帶來的舒適感。如果您需要框架來完成一些繁重的工作,您可以透過使用自訂方法聲明您自己的類別來擴展 SQL 映射器 - 但您無法避免在某些核心 SQL 上變得油膩:-
class Vendor extends DB SQL Mapper {
// Instantiate mapper
function __construct ( DB SQL $ db ) {
// This is where the mapper and DB structure synchronization occurs
parent :: __construct ( $ db , ' vendors ' );
}
// Specialized query
function listByCity () {
return $ this -> select (
' vendorID,name,city ' ,[ ' order ' => ' city DESC ' ]);
/ *
We could have done the the same thing with plain vanilla SQL : -
return $ this - > db - > exec (
'SELECT vendorID,name,city FROM vendors ' .
'ORDER BY city DESC;'
);
* /
}
}
$ vendor = new Vendor ;
$ vendor -> listByCity ();以這種方式擴展資料映射器是建立應用程式的資料庫相關模型的簡單方法。
如果您熟悉 SQL,您可能會說:ORM 中的所有內容都可以使用老式 SQL 查詢來處理。的確。我們可以透過使用資料庫觸發器和預存程序來不需要額外的事件偵聽器。我們可以透過連接表來完成關係查詢。 ORM 只是不必要的開銷。但重點是 - 資料映射器為您提供了使用物件來表示資料庫實體的附加功能。作為開發人員,您可以更快地編寫程式碼並提高工作效率。產生的程式即使不是更短,也會更乾淨。但您必須權衡速度的好處和速度的妥協 - 特別是在處理大型且複雜的資料儲存時。請記住,所有 ORMS(無論它們有多薄)都將始終只是另一個抽象層。他們仍然必須將工作傳遞給底層 SQL 引擎。
根據設計,F3 的 ORM 不提供直接將物件相互連接的方法,即 SQL 連接 - 因為這會引發大量蠕蟲病毒。它使您的應用程式比應有的更加複雜,並且由於物件繼承和與它們映射到的資料庫實體的多態性(阻抗不匹配),因此透過急切或惰性獲取技術的物件往往會陷入僵局,甚至不同步。在 SQL 映射器中可以透過使用虛擬欄位的間接方法來執行此操作,但您必須以程式設計方式執行此操作,並自行承擔風險。
如果您想在應用程式中應用「純」OOP 概念來表示所有資料(因為「一切都是物件」),請記住資料幾乎總是比應用程式存在得更久。您的程式可能早在資料失去價值之前就已經過時了。不要使用與資料的模式和物理結構相差太多的相互交織的物件和類,從而在程式中增加另一層複雜性。
在應用程式中將多個物件編織在一起以操作資料庫中的基礎表之前,請考慮一下:建立視圖來表示關係並建立觸發器來定義資料庫引擎中的物件行為會更有效。關係資料庫引擎旨在處理視圖、連接表和觸發器。它們不是愚蠢的資料儲存。加入檢視中的表將顯示為單一資料表,Fat-Free 可以像常規表一樣自動對應檢視。與資料庫引擎的機器碼、關係代數和最佳化邏輯相比,在 PHP 中將 JOIN 複製為關係物件要慢一些。此外,在我們的應用程式中重複連接表是資料庫設計需要審核的明確標誌,並且視圖被視為資料檢索的組成部分。如果一個表格經常交叉引用另一個表中的數據,請考慮標準化您的結構或建立視圖。然後建立一個映射器物件來自動映射該視圖。它更快並且需要更少的努力。
考慮在資料庫引擎內建立的 SQL 視圖:-
CREATE VIEW combined AS
SELECT
projects . project_id AS project,
users . name AS name
FROM projects
LEFT OUTER JOIN users ON
projects . project_id = users . project_id AND
projects . user_id = users . user_id ;您的應用程式程式碼變得簡單,因為它不必維護兩個映射器物件(一個用於專案表,另一個用於使用者)只是為了從兩個連接表中檢索資料:-
$ combined = new DB SQL Mapper ( $ db , ' combined ' );
$ combined -> load ([ ' project=? ' , 123 ]);
echo $ combined -> name ;提示:依設計用途使用這些工具。 Fat-Free 已經有一個容易使用的 SQL 助理。如果您需要更大的錘子,請使用它:)嘗試在便利性和性能之間尋求平衡。如果您正在處理複雜且遺留的資料結構,SQL 將始終是您的後備選擇。
插件只不過是使用框架內建插件來擴展 F3 特性和功能的自動載入類別。如果您想做出貢獻,請在 Google 線上論壇主辦的 Fat-Free 討論區留言,或在 FreeNode #fatfree IRC 頻道中告訴我們。其他人可能參與類似的項目。如果我們團結一致,框架社群將會非常感激。
在某些情況下,您可能希望使表單更安全地抵禦垃圾郵件機器人和惡意自動化腳本。 F3提供了一種captcha()方法,以產生具有隨機文字的圖像,這些文字僅被人類識別。
$ img = new Image ();
$ img -> captcha ( ' fonts/CoolFont.ttf ' , 16 , 5 , ' SESSION.captcha_code ' );
$ img -> render ();此範例會根據您所需的TRUETYPE字體產生隨機圖像。 fonts/資料夾是應用程式UI路徑中的子資料夾。第二個參數指示字體大小,第三個參數定義要產生的十六進位字元的數量。
最後一個參數代表F3變數名稱。這是F3將其等效的字串圖像儲存在這裡。為了製作字串重新載入安全性,我們指定了一個會話變數: - SESSION.captcha_code ,映射到$_SESSION['captcha_code'] ,您可以稍後使用它來驗證表單中的輸入元素是否符合該字串。
我們已經介紹了框架中幾乎所有可用的功能,以運行獨立的Web伺服器。對於大多數應用程序,這些功能將為您提供很好的服務。但是,如果您的應用程式需要網路上另一台Web伺服器的數據,該怎麼辦? F3具有在這種情況下為您提供幫助的Web插件: -
$ web = new Web ;
$ request = $ web -> request ( ' http://www.google.com/ ' );
// another way to do it : -
$ request =Web:: instance ()-> request ( ' http://www.google.com/ ' );這個簡單的範例將HTTP請求傳送到位於www.google.com上的頁面,並將其儲存在$request PHP變數中。 request()方法傳回包含HTTP回應的數組,以便$request['headers']和$request['body']分別代表回應標頭和車身。我們本來可以使用F3 :: SET指令保存內容,或直接將輸出直接傳達到我們的瀏覽器中。在網路上檢索另一個HTML頁面可能沒有任何實際目的。但是它在恢復應用程式中特別有用,例如查詢couchdb伺服器。
$ host = ' localhost:5984 ' ;
$ web -> request ( $ host . ' /_all_dbs ' ),
$ web -> request ( $ host . ' /testdb/ ' ,[ ' method ' => ' PUT ' ]);您可能已經注意到,您可以將一系列其他選項傳遞給request()方法: -
$ web -> request (
' https://www.example.com:443? ' .
http_build_query (
[
' key1 ' => ' value1 ' ,
' key2 ' => ' value2 '
]
),
[
' headers ' =>[
' Accept: text/html,application/xhtml+xml,application/xml ' ,
' Accept-Language: en-us '
],
' follow_location ' => FALSE ,
' max_redirects ' => 30 ,
' ignore_errors ' => TRUE
]
);如果啟用了框架變數CACHE ,並且如果遠端伺服器指示您的應用程式快取對HTTP請求的回應,則F3將符合請求並每次框架從應用程式接收類似的請求時檢索快取的回應,從而行事像瀏覽器。
fat-free將使用您的Web伺服器上可用的任何手段來運行request()方法:PHP流包裝器( allow_url_fopen ),curl模組或低階插座。
F3具有將檔案傳送至HTTP用戶端的實用程序,即滿足下載請求。您可以使用它隱藏下載檔案的真實路徑。這增加了一些安全層,因為如果使用者不知道檔案名稱及其位置,則無法下載檔案。這是完成的方式: -
$ f3 -> route ( ' GET /downloads/@filename ' ,
function ( $ f3 , $ args ) {
// send () method returns FALSE if file doesn ' t exist
if (!Web:: instance ()-> send ( ' /real/path/ ' . $ args [ ' filename ' ]))
// Generate an HTTP 404
$ f3 -> error ( 404 );
}
);如果您發現需要另一個Web伺服器來代表電腦處理數據,則request()方法也可以在複雜的SOAP或XML -RPC應用程式中使用 - 從而利用了分發計算的功能。 W3Schools.com在肥皂上有出色的教學。另一方面,TutorialSpoint.com提供了XML-RPC的不錯概述。
快取靜態網頁 - 因此,可以跳過某些路由處理程序中的程式碼,而不必重新處理範本 - 是減少Web伺服器的工作負載的一種方法,因此它可以專注於其他任務。您可以透過為$f3->route()方法提供第三個參數來啟動框架的快取引擎。只需在快取網頁到期之前指定秒數: -
$ f3 -> route ( ' GET /my_page ' , ' App->method ' , 60 );這是它的工作原理。在此範例中,當F3首次偵測到URL /my_page時,它執行由第二個參數表示的路由處理程序,並將所有瀏覽器輸出儲存到框架的內建快取(伺服器端)。瀏覽器可以自動傳送到使用者的網頁瀏覽器(客戶端),因此瀏覽器可以在60秒內將相同的請求傳送給伺服器,而是可以在本機檢索頁面。該框架將快取用於一個完全不同的目的 - 向其他用戶提供框架的數據,要求在60秒的時間範圍內提供相同的網頁。它跳過執行路線處理程序,並直接從磁碟上提供先前儲存的頁面。當有人試圖存取60秒計時器後存取相同的URL時,F3將使用新副本刷新快取。
帶有靜態資料的網頁是快取的最有可能的候選人。如果$f3->route()方法中的第三個參數為零或未指定,則fat-free不會在指定URL處快取網頁。 F3符合HTTP規格:只能快取取得和頭部請求。
設計應用程式時要考慮的重要一點。除非您了解客戶端快取可能不需要的副作用,否則請勿快取網頁。確保您在網頁上啟動與使用者會話狀態無關的網頁中的快取。
例如,您設計了您的網站,以使所有網頁都具有選單選項: "Home" , "About Us"和"Login" ,當使用者未登入您的應用程式時顯示。您也希望選單選項更改為: "Home" , "About Us" "About Us" "Logout" ,一旦使用者登入。無論使用者的會話狀態如何,IE已登錄或登錄,使用者的瀏覽器將在其"About Us"的會話狀態下對頁面的快照進行。現在,用戶可能已經登錄,但是選單選項仍然與沒有發生此類事件的情況相同。那不是我們從應用程式中想要的行為。
一些指針: -
GET快取。它不會快取提交的表單!在我們的範例中,「關於我們」的內容可能是靜態的,但選單不是。"About Us"頁面,請確保僅在未登入使用者時才可用。CACHE Global變量,以指向該驅動器。這將使您的應用程式像一級方程式賽車一樣運行。注意:不要將超時值設定為很長的時間,直到您準備推出應用程序,即發布或生產狀態。如果頁面在框架快取中存在且到期期間內未段落,則您對任何PHP腳本進行的變更可能會對顯示的輸出產生預期影響。如果您確實更改了一個程序,則該程序產生了由快取計時器影響的頁面,並且希望這些變更立即生效,則應透過刪除快取/目錄中的檔案(或CACHE Global變數指向)中的檔案來清除快取。如有必要,F3將自動刷新快取。在客戶端,您幾乎無能為力,但指示使用者清除瀏覽器的快取或等待快取期過期。
需要正確設定PHP,以使F3快取引擎正常運作。您的作業系統時區應與php.ini檔案中的日期設定同步。
與路線類似,無脂肪也允許您快取資料庫查詢。速度成長可能非常重要,特別是在複雜的SQL語句上使用,這些語句涉及尋找很少更改的靜態資料或資料庫內容。啟動資料庫查詢緩存,因此框架不必重新執行SQL語句,就像在F3 :: SQL命令-SQL命令 - 快取逾時一樣簡單。例如:-
$ db -> exec ( ' SELECT * from sizes; ' , NULL , 86400 );如果我們期望此資料庫查詢的結果在24小時內總是Small , Medium且Large ,則指定86400秒為第二個參數,因此不必每天執行一次以上的查詢。取而代之的是,該框架將結果儲存在快取中,每次在指定的24小時時間範圍內提出請求時從快取中檢索它,並在計時器失效時重新執行查詢。
SQL資料映射器也使用快取引擎來優化表格結構與代表它們的物件的同步。預設值為60秒。如果您對資料庫引擎中的表結構進行任何更改,則必須等待快取計時器到期,然後才能看到應用程式中的效果。您可以透過向資料映射器建構函數指定第三個參數來變更此行為。如果您不希望對錶結構進行任何進一步的更改,則將其設為高價值。
$ user = new DB SQL Mapper ( $ db , ' users ' , 86400 );預設情況下,停用無脂肪的高速緩存引擎。您可以啟用它,並允許它自動偵測APC,Wincache或XCache。如果找不到合適的後端,F3將使用檔案系統,即tmp/cache/資料夾: -
$ f3 -> set ( ' CACHE ' , TRUE );禁用快取很簡單: -
$ f3 -> set ( ' CACHE ' , FALSE );如果您想覆蓋自動檢測功能,則可以這樣做 - 就像在後端的後端一樣,F3也支援: -
$ f3 -> set ( ' CACHE ' , ' memcache=localhost:11211 ' );您也可以使用快取引擎儲存自己的變數。這些變數將在HTTP請求之間持續存在,並保留在快取中,直到引擎收到指令刪除它們為止。為了在快取中保存值: -
$ f3 -> set ( ' var ' , ' I want this value saved ' , 90 ); $f3->set()方法的第三個參數指示該框架將變數保存在90秒的持續時間內。如果您的應用程式在此期間發出$f3->get('var') ,則F3將自動從快取中檢索值。以類似的方式, $f3->clear('var')將清除高速緩存和RAM的值。如果要確定緩存中是否存在變量,則`$ f3->存在('var'));傳回兩個可能的值之一:false如果框架變數在快取中不存在,則或代表變數保存時間的整數(以秒為單位,以微秒精度為單位)。
fat-fire,在Web插件中還具有JavaScript和CSS壓縮機。它可以將所有CSS檔案組合到一個樣式表(或JavaScript檔案中)中,因此減少了網頁上的元件數量。將HTTP請求的數量減少到您的Web伺服器,從而更快地載入頁面載入。首先,您需要準備HTML模板,以便它可以利用此功能。類似: -
< link rel =" stylesheet " type =" text/css "
href =" /minify/css?files=typo.css,grid.css " />對您的JavaScript檔案進行相同的操作: -
< script type =" text/javascript " src =" /minify/js?&files=underscore.js " >
</ script >當然,我們需要設定一條路線,以便您的應用程式可以處理對無脂肪CSS/JavaScript壓縮機的必要呼叫: -
$ f3 -> route ( ' GET /minify/@type ' ,
function ( $ f3 , $ args ) {
$ f3 -> set ( ' UI ' , $ args [ ' type ' ]. ' / ' );
echo Web:: instance ()-> minify ( $ _GET [ ' files ' ]);
},
3600
);這就是全部! minify()在我們的css範例中讀取每個檔案( typo.css and grid.css ,在我們的javascript範例中下underscore.js ),剝離所有不必要的whitespaces和評論,將所有相關項目組合為單一網頁元件,以及附加遙遠的到期日期,以便使用者的網頁瀏覽器可以快取資料。重要的是, PARAMS.type變數基本上指向正確的路徑很重要。否則,壓縮機內的URL重寫機制將找不到CSS/JavaScript檔。
在我們的範例中,該框架向客戶端的網頁瀏覽器發送了一個遙遠的到期日期,因此對相同CSS或JavaScript區塊的任何請求都將來自使用者的硬碟。在伺服器端,F3將檢查每個請求,並查看CSS或JavaScript區塊是否已快取。我們指定的路線具有3600秒的快取刷新時間。此外,如果網頁瀏覽器發送If-Modified-Since請求標題,且該框架看到快取尚未更改,則F3僅發送HTTP 304 Not Modified回應,因此實際上沒有提供任何內容。如果沒有If-Modified-Since標頭,則無脂肪會呈現快取檔案的輸出。否則,執行相關程式碼。
提示:如果您不經常修改JavaScript/CSS檔案(就像您使用JQUERY,MOOTOOLS,DOJO等這樣的JavaScript庫一樣),請考慮將快取計時器添加到通往JavaScript的路線中/CSS縮放處理程序(F3 :: Route()的第三個參數())因此,每次收到此類請求時,fate-free都不會壓縮並組合這些檔案。
想讓您的網站運作速度更快嗎?無脂肪的替代性PHP快取(APC),XCACHE或WINCACHE最有效。這些PHP擴充功能透過優化您的PHP腳本(包括框架程式碼)來提高應用程式的效能。
一個快速處理所有HTTP請求並在最短時間響應它們的快速應用程式並不總是一個好主意 - 特別是如果您的頻寬有限,或者網站上的流量特別重。盡快服務頁面還使您的應用程式容易受到拒絕服務(DOS)攻擊。 F3具有頻寬節流功能,可讓您控制提供網頁的速度。您可以指定處理請求需要多少時間: -
$ f3 -> route ( ' /throttledpage ' , ' MyApp->handler ' , 0 , 128 );在此範例中,該框架將以128kibps的速度提供網頁。
在應用程式層級上節流的頻寬對於登入頁面特別有用。對字典攻擊的緩慢回應是減輕這種安全風險的好方法。
強大的應用是全面測試的結果。驗證程式的每個部分是否符合規格,並符合最終用戶的期望,這意味著在應用程式開發週期中找到錯誤並儘早解決它們。
如果您對單元測試方法幾乎一無所知,則可能直接將程式碼嵌入現有程式中以幫助您進行偵錯。當然,這意味著您必須在程式運行後刪除它們。剩餘的程式碼片段,設計差和實作錯誤的實作可能會在您以後推出應用程式時作為錯誤。
F3讓您可以輕鬆調試程式 - 而無需妨礙您的常規思考過程。該框架不需要您建造複雜的OOP類,重型測試結構和令人難以置信的程序。
單位(或測試固定裝置)可以是功能/方法或類別。讓我們有一個簡單的例子: -
function hello () {
return ' Hello, World ' ;
}將其保存在名為hello.php的檔案中。現在,我們怎麼知道它真的能如預期運作?讓我們創建我們的測試程式: -
$ f3 = require ( ' lib/base.php ' );
// Set up
$ test = new Test ;
include ( ' hello.php ' );
// This is where the tests begin
$ test -> expect (
is_callable ( ' hello ' ),
' hello() is a function '
);
// Another test
$ hello = hello ();
$ test -> expect (
! empty ( $ hello ),
' Something was returned '
);
// This test should succeed
$ test ->expect
is_string ( $ hello ),
' Return value is a string '
);
// This test is bound to fail
$ test -> expect (
strlen ( $ hello )== 13 ,
' String length is 13 '
);
// Display the results ; not MVC but let ' s keep it simple
foreach ( $ test -> results () as $ result ) {
echo $ result [ ' text ' ]. ' <br /> ' ;
if ( $ result [ ' status ' ])
echo ' Pass ' ;
else
echo ' Fail ( ' . $ result [ ' source ' ]. ' ) ' ;
echo ' <br /> ' ;
}將其保存在名為test.php的檔案中。這樣,我們可以保留hello.php的完整性。
現在,這是我們單元測試過程的肉。
F3的內建Test類別追蹤每個expect()呼叫的結果。 $test->results()的輸出是帶有鍵text的陣列數組(鏡像參數2 expect() ), status (布林值代表測試的結果)和source (檔案名稱/行號的檔案名稱/行號具體測試)有助於調試。
無脂肪使您可以自由以任何方式顯示測試結果。您可以將輸出以純文字或甚至看起來不錯的HTML範本。那我們要如何進行單位測試呢?如果將test.php保存在文件根資料夾中,則可以開啟瀏覽器並指定位址http://localhost/test.php 。這就是全部內容了。
F3可讓您從PHP程式模擬HTTP請求,以便您可以測試特定路線的行為。這是一個簡單的模擬請求: -
$ f3 -> mock ( ' GET /test?foo=bar ' );嘲笑發布請求並提交模擬的HTML表格: -
$ f3 -> mock ( ' POST /test ' ,[ ' foo ' => ' bar ' ]);一旦掌握了測試應用程式的最小單元,就可以轉到較大的組件,模組和子系統 - 一路檢查零件是否相互正確通訊。測試可管理的大量程式碼會導致您預期的更可靠的程序,並將測試過程編織到開發週期的結構中。要問自己的問題是: - 我是否測試了所有可能的情況?通常,那些尚未考慮的情況是造成錯誤的原因。單位測試有助於最大程度地減少這些事件。即使在每個固定裝置上進行的一些測試也可以大大減輕頭痛。另一方面,在沒有單位測試的情況下編寫應用程式都會造成麻煩。
string AGENT
Mozilla/5.0 (Linux; Android 4.2.2; Nexus 7) AppleWebKit/537.31 。 bool AJAX
TRUE如果偵測到XML HTTP請求,否則為FALSE 。 string AUTOLOAD
| ),逗號( , )或半柱( ; )作為路徑分離器。 string BASE
index.php主/前控制器的路徑。 string BODY
bool/string CACHE
'memcache=localhost' (以及PHP memcache模組),F3自動檢測APC,Wincache和Xcache的存在,並使用第一個可用的PHP模組(如果設定為true)。如果這些PHP模組都不可用,則使用基於檔案系統的後端(預設目錄: tmp/cache )。該框架如果分配了一個FALSE值,則會停用快取引擎。 bool CASELESS
FALSE以使其對病例敏感。 array COOKIE, GET, POST, REQUEST, SESSION, FILES, SERVER, ENV
integer DEBUG
string DNSBL
403 Forbidden錯誤。 array DIACRITICS
string ENCODING
UTF-8 。 array ERROR
ERROR.code是HTTP狀態碼。 ERROR.status包含對錯誤的簡要說明。 ERROR.text提供了更多細節。對於HTTP 500錯誤,請使用ERROR.trace檢索堆疊追蹤。 bool ESCAPE
string EXEMPT
string FALLBACK
bool HALT
array HEADERS
bool HIGHLIGHT
TRUE (需要code.css樣式表)。 string HOST
$_SERVER['SERVER_NAME'] ,則使用gethostname()的回傳值。 string IP
array JAR
string LANGUAGE
LOCALES指向的資料夾中。如果設定為NULL ,則可以從HTTP Accept-Language請求標頭自動偵測語言。 string LOCALES
string LOGS
mixed ONERROR
string PACKAGE
array PARAMS
route()模式中定義的令牌的擷取值。 PARAMS.0包含相對於Web根的捕獲的URL。 string PATTERN
string PLUGINS
base.php的路徑。 int PORT
string PREFIX
bool QUIET
bool RAW
BODY 。處理來自php://input大型資料時,此資料不適合記憶體。預設值: FALSE string REALM
string RESPONSE
QUIET設定如何。 string ROOT
array ROUTES
string SCHEME
http或https 。 string SERIALIZER
php ,除非自動偵測PHP igbinary擴展。如果需要指派json 。 string TEMP
tmp/夾。相應調整以符合您網站的安全策略。 string TZ
date_default_timezone_set()函數。 string UI
View和Template類別「 render()方法使用的使用者介面檔案。預設值是Web根。接受管道( | ),逗號( , )或半柱( ; )作為多個路徑的分離器。 callback UNLOAD
string UPLOADS
string URI
string VERB
string VERSION
@token
@token用等效F3變數的值替換。 {{ mixed expr }}
expr可能包括模板令牌,常數,運算子(一元,算術,三元和關係),括號,資料類型轉換器和功能。如果不是模板指令的屬性,則結果將迴盪。 {{ string expr | raw }}
expr 。預設情況下,F3自動移動字串。 {{ string expr | esc }}
expr 。這是預設框架行為。 | esc僅當ESCAPE Global變數設定為FALSE時才需要| esc字尾。 {{ string expr, arg1, ..., argN | format }}
expr並通過逗號分隔的參數,其中arg1, ..., argn是: - 'date' , 'time' , 'number, integer' , 'number, currency'或'number, percent' 。 <include
[ if="{{ bool condition }}" ]
href="{{ string subtemplate }}"
/>
TRUE則取得subtemplate的內容,並在範本中插入。 <exclude>text-block</exclude>
text-block 。用於將評論嵌入模板中。 <ignore>text-block</ignore>
text-block AS,而無需透過範本引擎進行解釋/修改。 <check if="{{ bool condition }}">
<true>true-block</true>
<false>false-block</false>
</check>
TRUE ,那麼就會呈現true-block 。否則,使用false-block 。 <loop
from="{{ statement }}"
to="{{ bool expr }}"
[ step="{{ statement }}" ]>
text-block
</loop>
from聲明中評估一次。檢查to中的表達式是否為TRUE ,呈現text-block並評估step語句。重複迭代, to表達為FALSE 。 <repeat
group="{{ array @group|expr }}"
[ key="{{ scalar @key }}" ]
value="{{ mixed @value }}"
[ counter="{{ scalar @key }}" ]>
text-block
</repeat>
text-block與陣列變數@group或表達式expr中的元素一樣多次。 @key和@value函數的方式與等效php foreach()語句中的鍵值對相同。每次迭代中以counter屬性增量為1的key表示的變數。 <switch expr="{{ scalar expr }}">
<case value="{{ scalar @value|expr }}" break="{{ bool TRUE|FALSE }}">
text-block
</case>
.
.
.
</switch>
{* text-block *}
<exclude> 。最新的文檔位於http://fatfreeframework.com/。它包含使用各種框架組件的範例。
技術支援可在官方討論論壇上獲得: https://groups.google.com/forum/#!forum/f3-framework 。如果您需要即時支持,則可以透過Slack或IRC與開發團隊和F3社群的其他成員進行交談。我們在FreeNode #fatfree頻道( chat.freenode.net )上。請造訪http://webchat.freenode.net/參加對話。如果沒有IRC客戶端,也可以下載Firefox Chatzilla附加元件或Pidgin,以便您可以參加即時聊天。您也可以在堆疊溢位中找到幫助
F3使用git進行版本控制。在GitHub上克隆最新的程式碼儲存庫:
git clone git://github.com/bcosca/fatfree-core.git如果您想要的只是所有單位測試的測試台的拉鍊,請在此處獲取。
若要提交錯誤報告,請造訪https://github.com/bcosca/fatfree-core/issues 。
無脂肪的框架是免費的,並作為GNU公共許可證(GPL V3)涵蓋的開源軟體發布。除了符合許可證外,您不得使用軟體,文件和樣品。如果此許可證的條款和條件過於限制您的使用,則可以以非常合理的費用獲得替代許可。
如果您認為該軟體是在您的程式設計阿森納中擁有的一種很好的武器,它可以節省大量時間和金錢,將其用於商業收益或商業組織,請考慮向專案捐款。大量的時間,精力和金錢已經花在了這個專案上。您的捐款有助於維持該專案的活力,開發團隊的動機。捐款者和贊助商獲得優先支援(在工作日為24小時的回應時間)。
無脂肪的框架是社群驅動的軟體。沒有以下人員和組織的幫助和支持,今天就不可能是什麼:
特別感謝其他無私的人表示希望保持匿名,但分享時間,貢獻代碼,發送捐款,向更廣泛的受眾推廣框架,並提供鼓勵和定期的財務援助。他們的慷慨是F3的主要動機。

透過向該項目捐款,您表示您承認,瞭解,接受並同意本通知中包含的條款和條件。您對無脂肪框架項目的捐款是自願的,對於任何服務,商品或優勢而不是費用,並且向該項目捐款並不使您獲得任何服務,商品或優勢。我們有權以任何合法的方式使用您捐贈給無脂肪框架項目的錢,除非適用法律要求,否則我們沒有義務向任何一方披露任何一方的方式和目的。儘管無脂肪的框架是自由軟體,但據我們所知,該專案沒有任何免稅狀態。無脂肪的框架計畫既不是註冊的非營利公司,也不是任何國家的註冊慈善機構。您的捐款可能可以免稅,也可能不能免稅;請與您的稅務顧問諮詢。除非適用法律要求,否則我們不會未經您同意即可發布/揭露您的姓名和電子郵件地址。您的捐款不可退還。
版權所有(C)2009-2022 F3 :: Factory/Bong Cosca <[email protected]>
嘿夥計!幫我幾個吧!