強力でありながら使いやすい PHP マイクロフレームワークは、動的で堅牢な Web アプリケーションを迅速に構築できるように設計されています。
約 65 KB の単一ファイルに凝縮された F3 (私たちが親しみを込めてそう呼んでいます) は、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
経験豊富なユーザーは、更新されたコード ベースと継続的な改善を活用するために、最新バージョンで新しいアプリケーションを開発することを強くお勧めします。
最新のユーザー ガイドと、多数のコード例とグラフィック ガイドを含む詳細な API ドキュメントは、fatfreeframework.com/ で見つけることができます。
もちろん、この便利なオンライン リファレンスは F3 によってサポートされています。フレームワークの機能とパフォーマンスを示します。今すぐチェックしてください。 github で直接読みたい場合は、github.com/F3Community/F3com-data で Web サイトのコンテンツを見つけることができます。
デザイナーは、追加するものが何も残っていないときではなく、取り除くものが何も残っていないときに、自分が完璧に達したと知ります。 -- アントワーヌ・ド・サン=テグジュペリ
Fat-Free Framework を使用すると、Web サイト全体を短時間で簡単に構築できます。最新の Javascript ツールキットやライブラリと同じ能力と簡潔さを備えた F3 は、見た目が良く、より信頼性の高い PHP プログラムを作成するのに役立ちます。 PHP ソース コードを一目見るだけで、わずかなコード行でどれだけのことを達成できるか、そしてその結果がどれほど強力であるかを誰でも簡単に理解できるでしょう。
F3 は、文書化されたフレームワークの中で最も優れたものの 1 つです。それを学ぶのにほとんど費用はかかりません。ナビゲートが難しいディレクトリ構造や煩雑なプログラミング手順の厳密なセットはありません。ブラウザに'Hello, World'
を表示するためだけに、設定オプションを大量に積み込む必要はありません。 Fat-Free を使用すると、より多くの作業を簡単に、より短時間で完了できるよう、多くの自由とスタイルが得られます。
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
シェル、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
として保存します。最初の Web ページを作成しました。
コンポーザーを使用していますか?次に、 composer require bcosca/fatfree
を実行し、以下を使用します。
require ' vendor/autoload.php ' ;
$ f3 = Base:: instance ();
$ f3 -> route ( ' GET / ' ,
function () {
echo ' Hello, world! ' ;
}
);
$ f3 -> run ();
最初のコマンドは、フレームワークの機能をアプリケーションで利用できるようにすることを PHP インタープリタに伝えます。 $f3->route()
メソッドは、スラッシュ ( /
) で示された相対 URL で Web ページが利用可能であることを Fat-Free に通知します。 http://www.example.com/
にあるサイトにアクセスすると'Hello, world!'
メッセージが表示されます。 URL /
はルート ページに相当するため、メッセージが表示されます。 http://www.example.com/inside/
など、ルート ページから分岐するルートを作成するには、単純なGET /inside
文字列を使用して別のルートを定義できます。
上で説明したルートは、HTTP GET
メソッドを使用して URL リクエストを受信した場合にのみページをレンダリングするようにフレームワークに指示します。フォームを含むより複雑な Web サイトでは、 POST
などの他の HTTP メソッドが使用され、これを$f3->route()
仕様の一部として実装することもできます。
フレームワークは、ルート URL /
にある Web ページに対する受信リクエストを認識すると、そのリクエストをコールバック関数に自動的にルーティングします。コールバック関数には、リクエストを処理して適切な HTML 要素をレンダリングするために必要なコードが含まれています。この例では、文字列'Hello, world!'
を送信するだけです。ユーザーの Web ブラウザに送信されます。
これで最初のルートが確立されました。しかし、それを処理するプロセスが存在し、ユーザーの Web ブラウザに表示するテキストがあることを F3 に知らせること以外は、あまり役に立ちません。サイトにさらに多くのページがある場合は、グループごとに異なるルートを設定する必要があります。とりあえずはシンプルにしておきましょう。フレームワークにリクエストの待機を開始するように指示するには、 $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 ' );
渡される引数は常に 2 番目のパラメータとして提供されます。
$ f3 -> route ( ' GET /hello/@name ' , ' User::greet ' );
class User {
public static function greet ( $ f3 , $ args ) { // $ args is type of Array
echo " Hello " . $ args [ ' name ' ];
}
}
指定された 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. ' ;
}
);
この例では、URL の一部を表すトークン@count
指定する方法を示します。フレームワークは、 /brew/
接頭辞に一致するリクエスト URL ( /brew/99
、 /brew/98
など) を処理します。これにより'99 bottles of beer on the wall'
と'98 bottles of beer on the wall'
、 それぞれ。 Fat-Free は、 /brew/unbreakable
のページ リクエストも受け入れます。 (これは、 'unbreakable bottles of beer on the wall'
が表示されることを期待してください。) このような動的ルートが指定されると、Fat-Free は、URL 内でキャプチャされた文字列の値をグローバルPARAMS
配列変数に自動的に設定します。コールバック関数内の$f3->get()
呼び出しは、フレームワーク変数の値を取得します。このメソッドは、プレゼンテーションまたはビジネス ロジックの一部としてコードに確実に適用できます。ただし、これについては後ほど詳しく説明します。
Fat-Free は配列のドット表記を理解することに注意してください。タイプミスやアンバランスな中括弧が発生しやすいコードでは、代わりにPARAMS['count']
通常の表記法を使用できます。ビューとテンプレートでは、フレームワークは Javascript に似た@PARAMS.count
表記を許可します。 (ビューとテンプレートについては後で説明します。)
リクエスト パターンでトークンにアクセスする別の方法は次のとおりです。
$ 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 (そして自分自身) が混乱することになります。どちらかを使用してください。もう 1 つ: 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
ハイブ配列のキーとして名前付きルートの値を取得します。
< 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 はそれらのトークンを現在の値に置き換えます。 reroute を呼び出す前にトークンの値を変更したい場合は、それを 2 番目の引数として渡します。:-
$ 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) ' );
整形式 URL に関する RFC 1738 ガイドラインに準拠していない文字がある場合は、必ず引数を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]
このスクリプトは、HTTP リクエストが到着し、物理ファイル ( !-f
)、パス ( !-d
)、またはシンボリック リンク ( !-l
) が見つからない場合は、必ず制御をindex.php
に転送するように Apache に指示します。メイン/フロント コントローラー、そしてフレームワークを呼び出します。
上記の Apache ディレクティブを含む.htaccess file
、常に、 index.php
と同じフォルダーに存在する必要があります。
また、ハードドライブ内のindex.php
の物理的な場所を認識できるようにApacheを設定する必要もあります。一般的な構成は次のとおりです。
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"
}
URL 書き換えモジュールと、Windows のバージョンに対応する適切な .NET Framework をインストールします。次に、次の内容を含む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://www.example.com/newpage
にリダイレクトします。上の例。 $f3->reroute('http://www.anotherexample.org/');
のように、ユーザーを別のサイトにリダイレクトすることもできます。 。
再ルーティングは、サイトでメンテナンス作業を行う必要がある場合に特に役立ちます。サイトが短期間オフラインであることを訪問者に通知するルート ハンドラーを使用できます。
HTTP リダイレクトは不可欠ですが、コストがかかる場合もあります。ターゲット ルートを処理する関数またはメソッドを呼び出してアプリケーションのフローを指示できる場合は、 $f3->reroute()
使用してユーザーを同じ Web サイトの別のページに送信することはできる限り控えてください。ただし、この方法では、ユーザーの 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 にはアプリケーションの構造方法に制限がありません。 Model-View-Controller パターンを使用したい場合は、F3 を使用すると、このパラダイムに従うようにアプリケーション コンポーネントを区分化することができます。一方、このフレームワークは Resource-Method-Representation パターンもサポートしており、実装はより簡単です。
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 インターフェイスを提供します。アプリケーションがGET /cart/123
のような受信 HTTP リクエストを受信すると、Fat-Free は自動的にオブジェクトまたはクラスのget()
メソッドに制御を移します。一方、 POST /cart/123
リクエストは、 Item
クラスのpost()
メソッドにルーティングされます。
注:ブラウザは、通常の HTML フォームに HTTP PUT
メソッドとDELETE
メソッドを実装しません。これらおよび他の ReST メソッド ( HEAD
およびCONNECT
) には、サーバーへの AJAX 呼び出しを介してのみアクセスできます。
フレームワークが、クラスによって実装されていないメソッドにマップされるルートに対する HTTP リクエストを受信した場合 (ルート マッピングでエラーが発生したか、メソッドがまだ作成されていない可能性があります)、 HTTP 405 Method Not Allowed
が生成されます。 HTTP 405 Method Not Allowed
エラー。
クライアントが URL リソースの HTTP OPTIONS
リクエストした場合、F3 は、リソースに対してどのメソッドが許可されているかを示す適切な HTTP ヘッダー (HEAD、GET、PUT など) で応答します。フレームワークはOPTIONS
リクエストをクラスにマップしません。
Fat-Free には、必要なときにのみクラスをロードする方法があるため、アプリケーションの特定のセグメントが必要とする以上のメモリを消費することはありません。また、別のファイルや別の場所に保存された PHP クラスをロードするためだけに、 include
やrequire
ステートメントの長いリストを記述する必要はありません。フレームワークはこれを自動的に実行します。ファイル (ファイルごとに 1 つのクラス) をフォルダーに保存し、クラス内のメソッドを呼び出したら適切なファイルを自動的にロードするようにフレームワークに指示するだけです。
$ 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 クラスを自動的にロードするには、 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 は、現在のルートに関連付けられたクラスまたはメソッド、つまり未定義のクラスまたはメソッドに制御を転送できない場合、実行時に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()
ステートメントを使用しません。すべてのフレームワーク定数はクラスに限定されます。
Fat-Free 変数に値を割り当てるには:
$ 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
注:ファットフリー変数は、オブジェクトや匿名関数を含むすべての 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 グローバルに相当する Fat-Free を設定すると、PHP の基礎となる$_SESSION
変更されます。後者を変更すると、対応するフレームワークも変更されます。 Fat-Free は、変数とその値を保存するだけのダムストレージを維持するわけではありません。セッション管理などを自動化することもできます。 F3 のSESSION
変数を介して値を割り当てたり取得したりすると、セッションが自動的に開始されます。フレームワーク変数SESSION
の代わりに$_SESSION
(またはセッション関連関数) を直接使用すると、アプリケーションがセッションを管理することになります。
原則として、フレームワーク変数は HTTP リクエスト間では保持されません。 PHP の$_SESSION
および$_COOKIE
グローバル変数にマップされるSESSION
およびCOOKIE
(およびその要素) のみが、HTTP のステートレスな性質から除外されます。
Fat-Free によって内部的に使用される事前定義されたグローバル変数がいくつかあり、それらをアプリケーションで確実に利用できます。自分が何をしているのかを必ず理解してください。一部の Fat-Free グローバル変数を変更すると、フレームワークの予期しない動作が発生する可能性があります。
フレームワークには、ファイルとディレクトリ構造を整理しておくのに役立ついくつかの変数があります。 AUTOLOAD
使用してクラスの読み込みを自動化する方法を見てきました。 UI
グローバル変数があり、これには HTML ビュー/テンプレートの場所を指すパスが含まれています。 DEBUG
アプリケーション開発中に頻繁に使用する変数で、エラー トレースの詳細度を設定するために使用されます。
組み込みフレームワーク変数の包括的なリストが必要な場合は、クイック リファレンスを参照してください。
フレームワーク変数には、任意の数の文字、数字、アンダースコアを含めることができます。英字で始める必要があり、スペースを含めることはできません。変数名では大文字と小文字が区別されます。
F3 は、内部の事前定義されたグローバル変数にすべて大文字を使用します。独自のプログラムですべて大文字で構成される変数名を使用することを妨げるものはありませんが、原則として、独自の変数を設定するときは小文字 (またはキャメルケース) を使用してください。これにより、現在および将来のフレームワーク リリースとの競合の可能性を回避できます。 。
if
、 for
、 class
、 default
などの PHP 予約語をフレームワーク変数名として使用しないでください。これらは予期しない結果を引き起こす可能性があります。
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 に設定しないと、Web サイトが不要なセキュリティ リスクにさらされる可能性があります。
アプリケーションをユーザーが構成できるようにする必要がある場合、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]
セクション ヘッダーは必須です。両方のセクションを 1 つの構成ファイルに結合できますが、 [routes]
と[maps]
を別のファイルに含めることをお勧めします。このようにして、エンドユーザーがアプリケーション固有のフラグを変更できるようにすると同時に、ルーティング ロジックへの干渉を制限できます。
HTML ページのようなユーザー インターフェイスは、ルーティングやビジネス ロジックに関連する基礎となる PHP コードから独立している必要があります。これは MVC パラダイムの基本です。 <h3>
を<p>
に変換するような基本的なリビジョンでは、アプリケーション コードの変更は必要ありません。同様に、 GET /about
のような単純なルートをGET /about-us
に変換しても、ユーザー インターフェイスとビジネス ロジック (MVC のビューとモデル、または RMR の表現とメソッド) に影響を与えることはありません。
スパゲッティ コーディングのように、プログラミング構造とユーザー インターフェイス コンポーネントを 1 つのファイルに混在させると、将来のアプリケーションのメンテナンスが悪夢のようになります。
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テンプレートトークンは@
シンボルで始まり、続いてカーリーブレースに囲まれた一連の文字と数字が続きます。最初のキャラクターはアルファでなければなりません。テンプレートトークンには、フレームワーク変数と1対1の対応があります。フレームワークは、トークンを同じ名前の変数に保存された値に自動的に置き換えます。
この例では、F3はテンプレート内の@name
トークンを名前変数に割り当てた値に置き換えます。実行時に、上記のコードの出力は次のとおりです。
< p > Hello, world </ p >
F3テンプレートのパフォーマンスが心配ですか?実行時に、フレームワークは、 $template->render()
を介して最初に表示されるときに、F3テンプレートをPHPコードに解析およびコンパイル/コンパイル/コンパイル/コンパイル/コンパイルします。フレームワークは、この後続のすべての呼び出しでこのコンパイルされたコードを使用します。したがって、パフォーマンスは、より複雑なテンプレートが関与している場合にテンプレートコンパイラによって行われたコード最適化のために、PHPテンプレートと同じである必要があります。
PHPのテンプレートエンジンを使用している場合でもF3の場合でも、APC、Wincache、Xcacheをサーバーで利用できる場合、テンプレートレンダリングは大幅に高速になります。
前述のように、フレームワーク変数は任意のPHPデータ型を保持できます。ただし、F3テンプレートでの非スカラーデータ型の使用は、注意しないと奇妙な結果が生じる可能性があります。巻き毛のブレースの式は常に評価され、弦に変換されます。ユーザーインターフェイス変数を単純なスカラーに制限する必要があります。- string
、 integer
、 boolean
、またはfloat
データ型。
しかし、配列はどうですか? FATフリーはアレイを認識し、テンプレートでそれらを使用できます。あなたは次のようなものを持つことができます: -
< p > {{ @buddy[0] }}, {{ @buddy[1] }}, and {{ @buddy[2] }} </ p >
テンプレートを提供する前に、PHPコードに@buddy
配列を入力します。
$ f3 -> set ( ' buddy ' ,[ ' Tom ' , ' Dick ' , ' Harry ' ]);
ただし、テンプレートに{{ @buddy }}
挿入するだけの場合、Tokenを文字列に変換するため、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') }}
単純な可変置換は、すべてのテンプレートエンジンが持っているものの1つです。脂肪のない袖はもっと上にあります: -
< 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>
ディレクティブを持つことができます。
NULL
、空の文字列、ブールのFALSE
、空の配列、またはゼロに相当する属性内のf3式は、 <false>
自動的に呼び出します。テンプレートに<false>
ブロックがない場合、 <true>
開閉タグはオプションです。
< check if =" {{ @loggedin }} " >
< p > HTML chunk to be included if condition is true </ p >
</ check >
脂肪なしは、繰り返しのHTMLブロックを処理することもできます: -
< repeat group =" {{ @fruits }} " value =" {{ @fruit }} " >
< p > {{ trim(@fruit) }} </ p >
</ repeat >
<repeat>
ディレクティブ内のgroup
属性@fruits
配列である必要があり、それに応じてPHPコードに設定する必要があります。
$ f3 -> set ( ' fruits ' ,[ ' apple ' , ' orange ' , ' banana ' ]);
アプリケーションコードで@fruit
に値を割り当てることで、何も得られません。 FATフリーは、グループを反復中に現在のアイテムを表すために変数を使用しているため、それが持つ可能性のあるプリセット値を無視します。上記の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でしなければならなかった唯一のことは、 @div
トークンを置き換えるために、単一のF3変数div
の内容を定義することでした。 FATフリーにより、プログラミングとWebテンプレートの両方のデザインが非常に簡単になります。
<repeat>
Template Directiveのvalue
属性は、イテレーションの現在の要素の値を返します。現在の要素の配列キーを取得する必要がある場合は、代わりにkey
属性を使用します。 key
属性はオプションです。
<repeat>
は、次のように使用できるオプションのカウンター属性もあります。-
< repeat group =" {{ @fruits }} " value =" {{ @fruit }} " counter =" {{ @ctr }} " >
< p class =" {{ @ctr%2?'odd':'even' }} " > {{ trim(@fruit) }} </ p >
</ repeat >
内部的には、F3のテンプレートエンジンはループイテレーションの数を記録し、変数/token @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フリーは変更されない限り、UTF-8文字セットを使用します。次のようなものを発行することで、この動作をオーバーライドできます。
$ f3 -> set ( ' ENCODING ' , ' ISO-8859-1 ' );
目的の文字セットのフレームワークを通知すると、F3は再び変更されるまですべてのHTMLおよびXMLテンプレートでそれを使用します。
このセクションで前述したように、フレームワークはHTMLテンプレートに限定されません。 XMLテンプレートも処理できます。メカニズムはほとんど似ています。まだ同じ{{ @variable }}
および{{ expression }}
トークン、 <repeat>
、 <check>
、 <include>
、 <exclude>
ディレクティブがあります。 f3にhtmlの代わりにxmlファイルを渡していることを伝えるだけです: -
echo Template:: instance ()-> render ( ' template.xml ' , ' application/xml ' );
2番目の引数は、レンダリングされているドキュメントの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 ' )
);
ヒント:SMTPメール()関数をIMAP_MAIL()に置き換えます。スクリプトがIMAPサーバーと通信した場合。
今、それは何かではありませんか?もちろん、電子メール受信者の束がある場合は、データベースを使用してFirstName、LastName、および電子メールトークンを入力します。
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は、すぐに複数の言語をサポートしています。
まず、次の構造を持つ辞書ファイルを作成します(言語ごとに1つのファイル): -
<?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/
folderで辞書を探すように指示します。
$ f3 -> set ( ' LOCALES ' , ' dict/ ' );
しかし、フレームワークはどの言語を使用するかをどのように決定しますか? F3は、最初にHTTPリクエストヘッダー、特にブラウザから送信されたAccept-Language
ヘッダーを調べることにより、自動的に検出されます。
この動作をオーバーライドするには、F3をトリガーしてユーザーまたはアプリケーションで指定された言語を使用できます。
$ f3 -> set ( ' LANGUAGE ' , ' de ' );
注:上記の例では、キーPIは英語辞書にのみ存在します。フレームワークは、指定された(または検出された)言語に存在しないキーを入力するためのフォールバックとして常に英語( en
)を使用します。
また、 en-US
、 es-AR
などの言語バリアントの辞書ファイルを作成することもできます。この場合、F3は最初に言語バリアント( es-AR
など)を使用します。バリアントに存在しないキーがある場合、フレームワークはルート言語( es
)のキーを検索し、 en
言語ファイルを最終フォールバックとして使用します。辞書のキー価値ペアは、参照されるとF3変数になります。キーが$f3->set()
、 $f3->mset()
、または$f3->config()
を介してインスタンス化されたフレームワーク変数と競合しないようにしてください。
前の例では'Today is {0,date}'
あることに気付きましたか? F3の多言語機能は、ICUプロジェクトの文字列/メッセージフォーマットルールにかかっています。フレームワークは、ICU文字列フォーマットの実装の独自のサブセットを使用します。サーバー上でPHPのintl
拡張機能をアクティブ化する必要はありません。
もう1つ: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 );
これには望ましくない効果があります。すべての変数がUNESCAPEDを通過することを望まない場合があります。脂肪なしでは、変数を個別に無効にすることができます。 F3テンプレートの場合: -
{{ @html_content | raw }}
PHPテンプレートの場合: -
<?php echo View:: instance ()-> raw ( $ html_content ); ?>
F3変数の自動エスケープに加えて、フレームワークはHTMLフォームからのユーザー入力を消毒するための自由な手を提供します。
$ f3 -> scrub ( $ _GET , ' p; br; span; div; a ' );
このコマンドは、指定された変数からすべてのタグ(2番目の引数で指定されているものを除く)と安全でない文字を削除します。変数に配列が含まれている場合、配列内の各要素は再帰的に消毒されます。アスタリスク(*)が2番目の引数として渡された場合、 $f3->scrub()
すべてのHTMLタグを許可し、手付かずの通過を許可し、単に安全でないコントロール文字を削除します。
FATフリーは、SQLデータベースとのインターフェースの仕事を簡単にするように設計されています。 SQLの詳細に没頭するタイプではなく、オブジェクト指向のデータ処理にもっと傾いている場合は、このチュートリアルの次のセクションに直接移動できます。ただし、複雑なデータ処理とデータベースのパフォーマンス最適化タスクを実行する必要がある場合は、SQLが最適です。
MySQL、SQLite、SQL Server、Sybase、OracleなどのSQLエンジンとの通信の確立は、馴染みのある$f3->set()
コマンドを使用して行われます。 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コマンドセットは、テンプレートのresult
配列変数を直接使用できるように、Web対応の結果を生成するのに十分である必要があります。それがそうであるように、脂肪のないものはあなたがそのSQLハンドラーの内部に入るのを止めません。実際、F3のDBSQL
クラスはPHPのPDO
クラスに直接派生しているため、細粒コントロールが必要な場合は、各プロセスに関与する基礎となるPDOコンポーネントとプリミティブにアクセスできます。
これが別の例です。 $db->exec()
コマンドへの引数として提供される単一のステートメントの代わりに、SQLステートメントの配列を渡すこともできます。
$ 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には、JIGと呼ばれる独自の高速で軽量のNOSQL実装があり、これは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
テーブルの構造を取得し、どのフィールドが主キーとして定義されているかを決定します。この時点で、Mapperオブジェクトにはまだデータが含まれていないため、 $user
構造化されたオブジェクトにすぎませんが、基本的なCRUD操作といくつかのエキストラを実行するために必要な方法が含まれています。文字列値tarzan
を含むuserID
フィールドを使用してユーザーテーブルからレコードを取得するには、 load() method
を使用します。このプロセスは、データマッパーオブジェクトの「自動hydrating」と呼ばれます。
簡単でしたか? 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 ' ]);
ジグを使用すると、構文はF3のテンプレートエンジンに似ています。
$ db = new DB Jig ( ' db/data/ ' , DB Jig:: FORMAT_JSON );
$ user = new DB Jig Mapper ( $ db , ' users ' );
$ user -> load ([ ' @userID=? ' , ' tarzan ' ]);
このフレームワークは、オブジェクト$user=new DBSQLMapper($db,'users');
インスタンス化中にテーブル内のフィールドvisits
データマッパープロパティに自動的にマッピングします。 。オブジェクトが作成されると、 $user->password
と$user->userID
それぞれテーブル内のpassword
とuserID
フィールドにマッピングされます。
マッピングされたフィールドを追加または削除したり、ORMを使用してテーブルの構造を変更したりすることはできません。これをMySQL、または使用しているデータベースエンジンでこれを行う必要があります。データベースエンジンに変更を加えた後、FATフリーは、アプリケーションを実行するときに新しいテーブル構造をデータマッパーオブジェクトと自動的に同期します。
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はレコードをいつ挿入または更新するかをどのようにして知るのでしょうか?データマッパーオブジェクトがレコードの検索によって自動hydrateされている時点で、フレームワークはレコードのプライマリキー(または_id
、MongoDBとJIGの場合)を追跡します。プライマリキーの値が変更されたとき。プログラムで潤滑されたデータマッパー - その値はデータベースから取得されませんでしたが、アプリケーションによって入力されます - は、その主要なキーに以前の値のメモリがありません。同じことがMongoDBとJIGにも当てはまりますが、オブジェクト_id
参照として使用します。したがって、上記の$user
オブジェクトをインスタンス化し、そのプロパティをプログラムの値に埋め込んだとき、ユーザーテーブルからレコードをまったく取得せずに、F3はこのレコードを挿入することを知っています。
save()
の後、マッパーオブジェクトは空になりません。データベースに新しいレコードを追加する場合は、最初にマッパーを脱水する必要があります。
$ user -> reset ();
$ user -> userID = ' cheetah ' ;
$ user -> password = password_hash ( ' unknown ' , PASSWORD_BCRYPT , [ ' cost ' => 12 ]);
$ user -> save ();
save()
呼び出すreset()
呼び出すことなく2回目は、Mapperが現在指し示しているレコードを単純に更新します。
データベース内のすべてのテーブルにプライマリキーを持っているという問題は議論的ですが、F3は、主要なキーを含むテーブルと通信するデータマッパーオブジェクトの作成を妨げません。唯一の欠点は、F3が参照しているレコードに加えて位置参照が信頼できないという事実を決定する方法がまったくないため、マッピングされたレコードを削除または更新することはできません。行IDは、さまざまなSQLエンジンでポータブルではなく、PHPデータベースドライバーによって返されない場合があります。
テーブルからマッピングされたレコードを削除するには、自動hydratedデータマッパーにerase()
メソッドを呼び出します。例えば:-
$ user = new DB SQL Mapper ( $ db , ' users ' );
$ user -> load ([ ' userID=? AND password=? ' , ' cheetah ' , ' ch1mp ' ]);
$ user -> erase ();
ジグのクエリ構文は少し似ています: -
$ 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 ();
マッパーオブジェクトのコンテナとして脂肪のない変数を使用できることに注意してください。 copyFrom()
メソッドは、マッパーオブジェクトをフレームワークアレイ変数の要素と補給します。その配列キーには、マッパーオブジェクトのプロパティと同一の名前が必要であり、レコードのフィールド名に対応する必要があります。したがって、Webフォームが送信されると(HTML名属性がuserID
に設定されていると仮定)、その入力フィールドの内容は$_POST['userID']
に転送され、 POST.userID
変数でF3によって複製され、保存されますマッピングされたフィールド$user->userID
。それらがすべて同じ名前の要素を持っている場合、プロセスは非常に簡単になります。配列キーの一貫性、つまりテンプレートトークン名、フレームワーク変数名、およびフィールド名が重要です:)
一方、レコードを取得し、テンプレートレンダリングなどの後で使用するためにフィールド値をフレームワーク変数にコピーしたい場合: -
$ f3 -> set ( ' user ' , new DB SQL Mapper ( $ db , ' users ' ));
$ f3 -> get ( ' user ' )-> load ([ ' userID=? ' , ' jane ' ]);
$ f3 -> get ( ' user ' )-> copyTo ( ' POST ' );
次に、{{ @post.userid}}を同じ入力フィールドの値属性に割り当てることができます。要約すると、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->skip()
、および$user->prev()
の代替品として$user->skip(-1)
$user->next()
を使用することができます。
dry()
メソッドを使用して、結果セットの制限を超えて操縦したかどうかを確認します。 dry()
最初のレコードでskip(-1)
試してみるとtrueを返します。また、検索基準を満たす最後のレコードでskip(1)
とtrueが返されます。
load()
メソッドは2番目の引数を受け入れます。次のようなキー価値ペアを含むオプションの配列が次のとおりです。
$ 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 ;
これは、小さなチャンクでデータを提示する1つの方法です。これが結果をページングする別の方法です: -
$ 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ミニオムを使用すると、既存のフィールドから派生したデータに取り組むことができます。
次の表が定義されているとします。-
CREATE TABLE products
productID VARCHAR ( 30 ),
description VARCHAR ( 255 ),
supplierID VARCHAR ( 30 ),
unitprice DECIMAL ( 10 , 2 ),
quantity INT ,
PRIMARY KEY (productID)
);
totalprice
フィールドは存在しないため、2つのフィールドの算術製品をデータベースエンジンに要求するフレームワークを伝えることができます。
$ item = new DB SQL Mapper ( $ db , ' products ' );
$ item -> totalprice = ' unitprice*quantity ' ;
$ item -> load ([ ' productID=:pid ' , ' :pid ' => ' apple ' ]);
echo $ item -> totalprice ;
上記のコードスニペットは、 unitprice
プライスにquantity
を乗算することによって計算されるtotalprice
と呼ばれる仮想フィールドを定義します。 SQL Mapperはそのルール/式を保存するため、データベースからレコードを取得する時が来たら、通常のマッピングフィールドのように仮想フィールドを使用できます。
より複雑な仮想フィールドを持つことができます: -
$ 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はsuppliers
テーブルにsupplerID
supplierID
を使用して、 products
テーブルのサプレリードを相互参照します。
仮想フィールドを破壊するには、 unset($item->totalPrice);
。 isset($item->totalPrice)
式は、 totalPrice
仮想フィールドが定義されている場合はtrueを返します。
データ取得の前に仮想フィールドを定義する必要があることを忘れないでください。 ORMは、実際の計算も、別のテーブルからの結果の導出も実行しません。すべてのハードワークを行うのはデータベースエンジンです。
レコードごとのナビゲーションが必要ない場合は、レコードのバッチ全体を1ショットで取得できます。
$ frequentUsers = $ user -> find ([ ' visits>? ' , 3 ],[ ' order ' => ' userID ' ]);
Jig Mapperのクエリ構文にはわずかな類似性があります。
$ 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()
に影響を与えません。
重要: find()
またはload()
の最初の引数として空の状態、null、またはゼロの長さの文字列を宣言すると、すべてのレコードが取得されます。あなたが何をしているのかを知っていることを確認してください - あなたは大きなテーブルまたはコレクションでPHPのMemory_limitを超えるかもしれません。
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! ' ;
find()
と同様のselect()
メソッドもありますが、返されたフィールドに対してより微調整された制御を提供します。 SQLのような構文があります: -
select (
' foo, bar, MIN(baz) AS lowest ' ,
' foo > ? ' ,
[
' group ' => ' foo, bar ' ,
' order ' => ' baz ASC ' ,
' limit ' => 5 ,
' offset ' => 3
]
);
find()
メソッドと同じように、 select()
マッパーオブジェクトの内容を変更しません。マップされたテーブルを照会するための便利な方法としてのみ機能します。両方の方法の返品値は、マッパーオブジェクトの配列です。 dry()
使用して、これらの方法のうちレコードが見つかったかどうかを判断します。 RECORDSが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 ();
この方法でデータマッパーを拡張することは、アプリケーションのDB関連モデルを簡単に構築する簡単な方法です。
SQLが便利な場合は、おそらく次のとおりです。ORMのすべては、古い学校のSQLクエリで処理できます。確かに。データベーストリガーとストアドプロシージャを使用して、追加のイベントリスナーなしで行うことができます。結合されたテーブルでリレーショナルクエリを達成できます。 ORMは不要なオーバーヘッドです。しかし、ポイントは、データマッパーを使用して、データベースエンティティを表すためにオブジェクトを使用する機能を追加することです。開発者として、コードをより速く書き、より生産的になることができます。結果として得られるプログラムは、短くないにしてもクリーンになります。ただし、大規模で複雑なデータストアを処理するときは、特に速度の妥協に対する利点を比較検討する必要があります。覚えておいてください、すべての骨は、どんなに薄くても - は常に別の抽象化レイヤーになります。彼らはまだ、基礎となるSQLエンジンに作業を渡す必要があります。
設計上、F3のORMは、オブジェクトを互いに直接接続する方法を提供しません。つまり、SQLが結合します。これにより、ワームの缶が開くためです。アプリケーションは本来よりも複雑になり、オブジェクトの継承と多型(インピーダンスミスマッチ)がマッピングされているデータベースエンティティと同期していない、熱心なまたは怠zyなフェッチングテクニックを通じてオブジェクトの傾向があります。 。仮想フィールドを使用して、SQL Mapperでそれを行うための間接的な方法がありますが、これをプログラムで、そしてあなた自身の責任で行う必要があります。
アプリケーションに「純粋な」OOPコンセプトを適用してすべてのデータを表現するように誘惑されている場合(「すべてがオブジェクトである」ため)、データはほとんど常にアプリケーションよりも長く存在することに留意してください。あなたのプログラムは、データがその価値を失うずっと前にすでに時代遅れになっているかもしれません。データのスキーマと物理構造からあまりにも多く逸脱している絡み合ったオブジェクトとクラスを使用して、プログラムに別の複雑さの層を追加しないでください。
アプリケーションで複数のオブジェクトを織り込む前に、データベース内の基礎となるテーブルを操作するには、これについて考えてみてください。リレーショナルデータベースエンジンは、ビューを処理し、テーブルに結合し、トリガーを処理するように設計されています。彼らは愚かなデータストアではありません。ビューで結合されたテーブルは、単一のテーブルとして表示され、Fat Freeは通常のテーブルと同様にビューを自動マッピングできます。 PHPのリレーショナルオブジェクトとしての結合は、データベースエンジンのマシンコード、リレーショナル代数、および最適化ロジックと比較して遅くなります。また、アプリケーションでテーブルを繰り返し結合することは、データベース設計を監査する必要があることを確実に兆候であり、ビューはデータ取得の不可欠な部分と考えられています。テーブルが頻繁に別のテーブルからデータを相互参照する場合は、代わりに構造を正規化するか、ビューを作成することを検討してください。次に、マッパーオブジェクトを作成して、その表示を自動マップします。それはより速く、より少ない労力が必要です。
データベースエンジン内で作成されたこの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 ;
2つのマッパーオブジェクト(1つはプロジェクトテーブル用、もう1つはユーザー用)を維持する必要がないため、簡単になります。
$ combined = new DB SQL Mapper ( $ db , ' combined ' );
$ combined -> load ([ ' project=? ' , 123 ]);
echo $ combined -> name ;
ヒント:設計されているツールを使用します。 FATフリーには、使いやすいSQLヘルパーが既にあります。より大きなハンマーが必要な場合はそれを使用してください:)利便性とパフォーマンスのバランスをとるようにしてください。複雑でレガシーデータ構造に取り組んでいる場合、SQLは常にフォールバックになります。
プラグインは、F3の機能と機能を拡張するためにフレームワークのビルドインを使用する自動装飾クラスにすぎません。貢献したい場合は、Googleグループが主催する無脂肪ディスカッションエリアにメモを残すか、FreeNode #fatfree
IRCチャンネルで教えてください。他の誰かが同様のプロジェクトに関与している可能性があります。 The framework community will appreciate it a lot if we unify our efforts.
There might be instances when you want to make your forms more secure against spam bots and malicious automated scripts. F3 provides a captcha()
method to generate images with random text that are designed to be recognizable only by humans.
$ img = new Image ();
$ img -> captcha ( ' fonts/CoolFont.ttf ' , 16 , 5 , ' SESSION.captcha_code ' );
$ img -> render ();
This example generates an random image based on your desired TrueType font. The fonts/
folder is a subfolder within application's UI
path. The second parameter indicates the font size, and the third argument defines the number of hexadecimal characters to generate.
The last argument represents an F3 variable name. This is where F3 will store the string equivalent of the CAPTCHA image. To make the string reload-safe, we specified a session variable:- SESSION.captcha_code
which maps to $_SESSION['captcha_code']
, which you can use later to verify whether the input element in the form submitted matches this string.
We've covered almost every feature available in the framework to run a stand-alone Web server. For most applications, these features will serve you quite well. But what do you do if your application needs data from another Web server on the network? F3 has the Web plugin to help you in this situation:-
$ web = new Web ;
$ request = $ web -> request ( ' http://www.google.com/ ' );
// another way to do it : -
$ request =Web:: instance ()-> request ( ' http://www.google.com/ ' );
This simple example sends an HTTP request to the page located at www.google.com and stores it in the $request
PHP variable. The request()
method returns an array containing the HTTP response such that $request['headers']
and $request['body']
represent the response headers and body, respectively. We could have saved the contents using the F3::set command, or echo'ed the output directly to our browser. Retrieving another HTML page on the net may not have any practical purpose. But it can be particularly useful in ReSTful applications, like querying a CouchDB server.
$ host = ' localhost:5984 ' ;
$ web -> request ( $ host . ' /_all_dbs ' ),
$ web -> request ( $ host . ' /testdb/ ' ,[ ' method ' => ' PUT ' ]);
You may have noticed that you can pass an array of additional options to the request()
method:-
$ 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
]
);
If the framework variable CACHE
is enabled, and if the remote server instructs your application to cache the response to the HTTP request, F3 will comply with the request and retrieve the cached response each time the framework receives a similar request from your application, thus behaving like a browser.
Fat-Free will use whatever means are available on your Web server for the request()
method to run: PHP stream wrappers ( allow_url_fopen
), cURL module, or low-level sockets.
F3 has a utility for sending files to an HTTP client, ie fulfilling download requests. You can use it to hide the real path to your download files. This adds some layer of security because users won't be able to download files if they don't know the file names and their locations. Here's how it's done:-
$ 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 );
}
);
The request()
method can also be used in complex SOAP or XML-RPC applications, if you find the need for another Web server to process data on your computer's behalf - thus harnessing the power of distributing computing. W3Schools.com has an excellent tutorial on SOAP. On the other hand, TutorialsPoint.com gives a nice overview of XML-RPC.
Caching static Web pages - so the code in some route handlers can be skipped and templates don't have to be reprocessed - is one way of reducing your Web server's work load so it can focus on other tasks. You can activate the framework's cache engine by providing a third argument to the $f3->route()
method. Just specify the number of seconds before a cached Web page expires:-
$ f3 -> route ( ' GET /my_page ' , ' App->method ' , 60 );
仕組みは次のとおりです。 In this example, when F3 detects that the URL /my_page
is accessed for the first time, it executes the route handler represented by the second argument and saves all browser output to the framework's built-in cache (server-side). A similar instruction is automatically sent to the user's Web browser (client-side), so that instead of sending an identical request to the server within the 60-second period, the browser can just retrieve the page locally. The framework uses the cache for an entirely different purpose - serving framework-cached data to other users asking for the same Web page within the 60-second time frame. It skips execution of the route handler and serves the previously-saved page directly from disk. When someone tries to access the same URL after the 60-second timer has lapsed, F3 will refresh the cache with a new copy.
Web pages with static data are the most likely candidates for caching. Fat-Free will not cache a Web page at a specified URL if the third argument in the $f3->route()
method is zero or unspecified. F3 conforms to the HTTP specifications: only GET and HEAD requests can be cached.
Here's an important point to consider when designing your application. Don't cache Web pages unless you understand the possible unwanted side-effects of the cache at the client-side. Make sure that you activate caching on Web pages that have nothing to do with the user's session state.
For example, you designed your site in such a way that all your Web pages have the menu options: "Home"
, "About Us"
, and "Login"
, displayed when a user is not logged into your application. You also want the menu options to change to: "Home"
, "About Us"
, and "Logout"
, once the user has logged in. If you instructed Fat-Free to cache the contents of "About Us"
page (which includes the menu options), it does so and also sends the same instruction to the HTTP client. Regardless of the user's session state, ie logged in or logged out, the user's browser will take a snapshot of the page at the session state it was in. Future requests by the user for the "About Us"
page before the cache timeout expires will display the same menu options available at that time the page was initially saved. Now, a user may have already logged in, but the menu options are still the same as if no such event occurred. That's not the kind of behavior we want from our application.
Some pointers:-
GET
routes only. It will not cache submitted forms!Don't activate the cache on Web pages that at first glance look static. In our example, the "About Us" content may be static, but the menu isn't."About Us"
page, make sure it's available only when a user is not logged in.CACHE
global variable so it points to that drive. This will make your application run like a Formula 1 race car. Note: Don't set the timeout value to a very long period until you're ready to roll out your application, ie the release or production state. Changes you make to any of your PHP scripts may not have the expected effect on the displayed output if the page exists in the framework cache and the expiration period has not lapsed. If you do alter a program that generates a page affected by the cache timer and you want these changes to take effect immediately, you should clear the cache by erasing the files in the cache/ directory (or whatever path the CACHE
global variable points to) 。 F3 will automatically refresh the cache if necessary. At the client-side, there's little you can do but instruct the user to clear the browser's cache or wait for the cache period to expire.
PHP needs to be set up correctly for the F3 cache engine to work properly. Your operating system timezone should be synchronized with the date.timezone setting in the php.ini
file.
Similar to routes, Fat-Free also allows you to cache database queries. Speed gains can be quite significant, specially when used on complex SQL statements that involve look-up of static data or database content that rarely changes. Activating the database query cache so the framework doesn't have to re-execute the SQL statements every time is as simple as adding a 3rd argument to the F3::sql command - the cache timeout.例えば:-
$ db -> exec ( ' SELECT * from sizes; ' , NULL , 86400 );
If we expect the result of this database query to always be Small
, Medium
, and Large
within a 24-hour period, we specify 86400
seconds as the 2nd argument so Fat-Free doesn't have to execute the query more than once a day 。 Instead, the framework will store the result in the cache, retrieve it from the cache every time a request comes in during the specified 24-hour time frame, and re-execute the query when the timer lapses.
The SQL data mapper also uses the cache engine to optimize synchronization of table structures with the objects that represent them.デフォルトは60
秒です。 If you make any changes to a table's structure in your database engine, you'll have to wait for the cache timer to expire before seeing the effect in your application. You can change this behavior by specifying a third argument to the data mapper constructor. Set it to a high value if you don't expect to make any further changes to your table structure.
$ user = new DB SQL Mapper ( $ db , ' users ' , 86400 );
By default, Fat-Free's cache engine is disabled. You can enable it and allow it to auto-detect APC, WinCache or XCache. If it cannot find an appropriate backend, F3 will use the filesystem, ie the tmp/cache/
folder:-
$ f3 -> set ( ' CACHE ' , TRUE );
Disabling the cache is as simple as:-
$ f3 -> set ( ' CACHE ' , FALSE );
If you wish to override the auto-detection feature, you can do so - as in the case of a Memcached back-end which F3 also supports:-
$ f3 -> set ( ' CACHE ' , ' memcache=localhost:11211 ' );
You can also use the cache engine to store your own variables. These variables will persist between HTTP requests and remain in cache until the engine receives instructions to delete them. To save a value in the cache:-
$ f3 -> set ( ' var ' , ' I want this value saved ' , 90 );
$f3->set()
method's third argument instructs the framework to save the variable in the cache for a 90-second duration. If your application issues a $f3->get('var')
within this period, F3 will automatically retrieve the value from cache. In like manner, $f3->clear('var')
will purge the value from both cache and RAM. If you want to determine if a variable exists in cache, `$f3->exists('var')); returns one of two possible values: FALSE if the framework variable passed does not exist in cache, or an integer representing the time the variable was saved (Un*x time in seconds, with microsecond precision).
Fat-Free also has a Javascript and CSS compressor available in the Web plug-in. It can combine all your CSS files into one stylesheet (or Javascript files into a single script) so the number of components on a Web page are decreased. Reducing the number of HTTP requests to your Web server results in faster page loading. First you need to prepare your HTML template so it can take advantage of this feature. Something like:-
< link rel =" stylesheet " type =" text/css "
href =" /minify/css?files=typo.css,grid.css " />
Do the same with your Javascript files:-
< script type =" text/javascript " src =" /minify/js?&files=underscore.js " >
</ script >
Of course we need to set up a route so your application can handle the necessary call to the Fat-Free CSS/Javascript compressor:-
$ f3 -> route ( ' GET /minify/@type ' ,
function ( $ f3 , $ args ) {
$ f3 -> set ( ' UI ' , $ args [ ' type ' ]. ' / ' );
echo Web:: instance ()-> minify ( $ _GET [ ' files ' ]);
},
3600
);
And that's all there is to it! minify()
reads each file ( typo.css
and grid.css
in our CSS example, underscore.js
in our Javascript example), strips off all unnecessary whitespaces and comments, combines all of the related items as a single Web page component, and attaches a far-future expiry date so the user's Web browser can cache the data. It's important that the PARAMS.type
variable base points to the correct path. Otherwise, the URL rewriting mechanism inside the compressor won't find the CSS/Javascript files.
In our examples, the framework sends a far-future expiry date to the client's Web browser so any request for the same CSS or Javascript block will come from the user's hard drive. On the server side, F3 will check each request and see if the CSS or Javascript blocks have already been cached. The route we specified has a cache refresh period of 3600
seconds. Additionally, if the Web browser sends an If-Modified-Since
request header and the framework sees the cache hasn't changed, F3 just sends an HTTP 304 Not Modified
response so no content is actually delivered. Without the If-Modified-Since
header, Fat-Free renders the output from the cached file if available. Otherwise, the relevant code is executed.
Tip: If you're not modifying your Javascript/CSS files frequently (as it would be if you're using a Javascript library like jQuery, MooTools, Dojo, etc.), consider adding a cache timer to the route leading to your Javascript/CSS minify handler (3rd argument of F3::route()) so Fat-Free doesn't have compress and combine these files each time such a request is received.
Want to make your site run even faster? Fat-Free works best with either Alternative PHP Cache (APC), XCache, or WinCache. These PHP extensions boost performance of your application by optimizing your PHP scripts (including the framework code).
A fast application that processes all HTTP requests and responds to them at the shortest time possible is not always a good idea - specially if your bandwidth is limited or traffic on your Web site is particularly heavy. Serving pages ASAP also makes your application vulnerable to Denial-of-Service (DOS) attacks. F3 has a bandwidth throttling feature that allows you to control how fast your Web pages are served. You can specify how much time it should take to process a request:-
$ f3 -> route ( ' /throttledpage ' , ' MyApp->handler ' , 0 , 128 );
In this example, the framework will serve the Web page at a rate of 128KiBps.
Bandwidth throttling at the application level can be particularly useful for login pages. Slow responses to dictionary attacks is a good way of mitigating this kind of security risk.
Robust applications are the result of comprehensive testing. Verifying that each part of your program conforms to the specifications and lives up to the expectations of the end-user means finding bugs and fixing them as early as possible in the application development cycle.
If you know little or nothing about unit testing methodologies, you're probably embedding pieces of code directly in your existing program to help you with debugging. That of course means you have to remove them once the program is running. Leftover code fragments, poor design and faulty implementation can creep up as bugs when you roll out your application later.
F3 makes it easy for you to debug programs - without getting in the way of your regular thought processes. The framework does not require you to build complex OOP classes, heavy test structures, and obtrusive procedures.
A unit (or test fixture) can be a function/method or a class. Let's have a simple example:-
function hello () {
return ' Hello, World ' ;
}
Save it in a file called hello.php
. Now how do we know it really runs as expected? Let's create our test procedure:-
$ 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 /> ' ;
}
Save it in a file called test.php
. This way we can preserve the integrity of hello.php
.
Now here's the meat of our unit testing process.
F3's built-in Test
class keeps track of the result of each expect()
call. The output of $test->results()
is an array of arrays with the keys text
(mirroring argument 2 of expect()
), status
(boolean representing the result of a test), and source
(file name/line number of the specific test) to aid in debugging.
Fat-Free gives you the freedom to display test results in any way you want. You can have the output in plain text or even a nice-looking HTML template. So how do we run our unit test? If you saved test.php
in the document root folder, you can just open your browser and specify the address http://localhost/test.php
.それだけです。
F3 gives you the ability to simulate HTTP requests from within your PHP program so you can test the behavior of a particular route. Here's a simple mock request:-
$ f3 -> mock ( ' GET /test?foo=bar ' );
To mock a POST request and submit a simulated HTML form:-
$ f3 -> mock ( ' POST /test ' ,[ ' foo ' => ' bar ' ]);
Once you get the hang of testing the smallest units of your application, you can then move on to the bigger components, modules, and subsystems - checking along the way if the parts are correctly communicating with each other. Testing manageable chunks of code leads to more reliable programs that work as you expect, and weaves the testing process into the fabric of your development cycle. The question to ask yourself is:- Have I tested all possible scenarios? More often than not, those situations that have not been taken into consideration are the likely causes of bugs. Unit testing helps a lot in minimizing these occurrences. Even a few tests on each fixture can greatly reduce headaches. On the other hand, writing applications without unit testing at all invites trouble.
string AGENT
Mozilla/5.0 (Linux; Android 4.2.2; Nexus 7) AppleWebKit/537.31
. bool AJAX
TRUE
if an XML HTTP request is detected, FALSE
otherwise. string AUTOLOAD
|
), comma ( ,
), or semi-colon ( ;
) as path separator. string BASE
index.php
main/front controller. string BODY
bool/string CACHE
'memcache=localhost'
(and the PHP memcache module is present), F3 auto-detects the presence of APC, WinCache and XCache and uses the first available PHP module if set to TRUE. If none of these PHP modules are available, a filesystem-based backend is used (default directory: tmp/cache
). The framework disables the cache engine if assigned a FALSE
value. bool CASELESS
FALSE
to make it case-sensitive. array COOKIE, GET, POST, REQUEST, SESSION, FILES, SERVER, ENV
integer DEBUG
string DNSBL
403 Forbidden
error if the user's IPv4 address is listed on the specified server(s). array DIACRITICS
string ENCODING
UTF-8
. array ERROR
ERROR.code
is the HTTP status code. ERROR.status
contains a brief description of the error. ERROR.text
provides more detail. For HTTP 500 errors, use ERROR.trace
to retrieve the stack trace. bool ESCAPE
string EXEMPT
string FALLBACK
bool HALT
array HEADERS
bool HIGHLIGHT
TRUE
(requires code.css
stylesheet). string HOST
$_SERVER['SERVER_NAME']
is not available, return value of gethostname()
is used. string IP
array JAR
string LANGUAGE
LOCALES
. If set to NULL
, language is auto-detected from the HTTP Accept-Language
request header. string LOCALES
string LOGS
mixed ONERROR
string PACKAGE
array PARAMS
route()
pattern. PARAMS.0
contains the captured URL relative to the Web root. string PATTERN
string PLUGINS
base.php
. int PORT
string PREFIX
bool QUIET
bool RAW
BODY
. Should be TRUE when processing large data coming from php://input
which will not fit in memory. Default value: FALSE
string REALM
string RESPONSE
QUIET
setting. string ROOT
array ROUTES
string SCHEME
http
or https
. string SERIALIZER
php
, unless PHP igbinary
extension is auto-detected. Assign json
if desired. string TEMP
tmp/
folder inside the Web root. Adjust accordingly to conform to your site's security policies. string TZ
date_default_timezone_set()
function. string UI
View
and Template
classes' render()
method. Default value is the Web root. Accepts a pipe ( |
), comma ( ,
), or semi-colon ( ;
) as separator for multiple paths. callback UNLOAD
string UPLOADS
string URI
string VERB
string VERSION
@token
@token
with value of equivalent F3 variable. {{ mixed expr }}
expr
may include template tokens, constants, operators (unary, arithmetic, ternary and relational), parentheses, data type converters, and functions. If not an attribute of a template directive, result is echoed. {{ string expr | raw }}
expr
. F3 auto-escapes strings by default. {{ string expr | esc }}
expr
. This is the default framework behavior. | esc
suffix is only necessary if ESCAPE
global variable is set to FALSE
. {{ string expr, arg1, ..., argN | format }}
expr
and pass the comma-separated arguments, where arg1, ..., argn
is one of:- 'date'
, 'time'
, 'number, integer'
, 'number, currency'
, or 'number, percent'
. <include
[ if="{{ bool condition }}" ]
href="{{ string subtemplate }}"
/>
subtemplate
and insert at current position in template if optional condition is TRUE
. <exclude>text-block</exclude>
text-block
at runtime. Used for embedding comments in templates. <ignore>text-block</ignore>
text-block
as-is, without interpretation/modification by the template engine. <check if="{{ bool condition }}">
<true>true-block</true>
<false>false-block</false>
</check>
TRUE
, then true-block
is rendered. Otherwise, false-block
is used. <loop
from="{{ statement }}"
to="{{ bool expr }}"
[ step="{{ statement }}" ]>
text-block
</loop>
from
statement once. Check if the expression in the to
attribute is TRUE
, render text-block
and evaluate step
statement. Repeat iteration until to
expression is FALSE
. <repeat
group="{{ array @group|expr }}"
[ key="{{ scalar @key }}" ]
value="{{ mixed @value }}"
[ counter="{{ scalar @key }}" ]>
text-block
</repeat>
text-block
as many times as there are elements in the array variable @group
or the expression expr
. @key
and @value
function in the same manner as the key-value pair in the equivalent PHP foreach()
statement. Variable represented by key
in counter
attribute increments by 1
with every iteration. <switch expr="{{ scalar expr }}">
<case value="{{ scalar @value|expr }}" break="{{ bool TRUE|FALSE }}">
text-block
</case>
.
.
.
</switch>
{* text-block *}
<exclude>
.The most up-to-date documentation is located at http://fatfreeframework.com/. It contains examples of usage of the various framework components.
Technical support is available at the official discussion forum: https://groups.google.com/forum/#!forum/f3-framework
. If you need live support, you can talk to the development team and other members of the F3 community via Slack or IRC. We're on the FreeNode #fatfree
channel ( chat.freenode.net
). Visit http://webchat.freenode.net/
to join the conversation. You can also download the Firefox Chatzilla add-on or Pidgin if you don't have an IRC client so you can participate in the live chat. You can also find help at Stack Overflow
F3 uses Git for version control. To clone the latest code repository on GitHub:
git clone git://github.com/bcosca/fatfree-core.git
If all you want is a zipball of our test bench with all unit tests, grab it here .
To file a bug report, visit https://github.com/bcosca/fatfree-core/issues
.
Fat-Free Framework is free and released as open source software covered by the terms of the GNU Public License (GPL v3). You may not use the software, documentation, and samples except in compliance with the license. If the terms and conditions of this license are too restrictive for your use, alternative licensing is available for a very reasonable fee.
If you feel that this software is one great weapon to have in your programming arsenal, it saves you a lot of time and money, use it for commercial gain or in your business organization, please consider making a donation to the project. A significant amount of time, effort, and money has been spent on this project. Your donations help keep this project alive and the development team motivated. Donors and sponsors get priority support (24-hour response time on business days).
The Fat-Free Framework is community-driven software. It can't be what it is today without the help and support from the following people and organizations:
Special thanks to the selfless others who expressed their desire to remain anonymous, yet share their time, contribute code, send donations, promote the framework to a wider audience, as well as provide encouragement and regular financial assistance. Their generosity is F3's prime motivation.
By making a donation to this project you signify that you acknowledged, understood, accepted, and agreed to the terms and conditions contained in this notice. Your donation to the Fat-Free Framework project is voluntary and is not a fee for any services, goods, or advantages, and making a donation to the project does not entitle you to any services, goods, or advantages. We have the right to use the money you donate to the Fat-Free Framework project in any lawful way and for any lawful purpose we see fit and we are not obligated to disclose the way and purpose to any party unless required by applicable law. Although Fat-Free Framework is free software, to our best knowledge this project does not have any tax-exempt status. The Fat-Free Framework project is neither a registered non-profit corporation nor a registered charity in any country. Your donation may or may not be tax-deductible; please consult this with your tax advisor. We will not publish/disclose your name and e-mail address without your consent, unless required by applicable law. Your donation is non-refundable.
Copyright (c) 2009-2022 F3::Factory/Bong Cosca <[email protected]>
おい、おい!いくつか手伝ってください!