フライトは、PHPのための高速でシンプルで拡張性のあるフレームワークです。非常に汎用性があり、あらゆる種類のWebアプリケーションの構築に使用できます。 シンプルさを重視して構築されており、理解しやすく使用しやすい方法で書かれています。
フレームワークを使用するメリットについて簡潔な記事がこちらにあります。フレームワークを使用する前に、その利点を理解することが重要です。
さらに、@lubianaによって優れたチュートリアルが作成されました。Flightに特化しているわけではありませんが、 このガイドはフレームワークを取り巻く主要なコンセプトとその使用上の利点を理解するのに役立ちます。 チュートリアルはこちらで見つけることができます。
Laravel、Slim、Fat-Free、Symfonyなどの他のフレームワークからFlightに移行している場合、このページは両者の違いを理解するのに役立ちます。
アプリケーション内で自分自身のクラスをオートロードする方法を学びます。
Webアプリケーションのためのルートを管理する方法を学びます。これにはルートのグルーピング、ルートパラメータ、ミドルウェアも含まれます。
リクエストとレスポンスをフィルタリングするためにミドルウェアを使用する方法を学びます。
アプリケーション内でリクエストとレスポンスを処理する方法を学びます。
ユーザーにレスポンスを送信する方法を学びます。
組み込みのビューエンジンを使用してHTMLテンプレートをレンダリングする方法を学びます。
一般的なセキュリティ脅威からアプリケーションを保護する方法を学びます。
アプリケーションにフレームワークを設定する方法を学びます。
独自のメソッドとクラスを追加してフレームワークを拡張する方法を学びます。
イベントシステムを使用してメソッドと内部フレームワークメソッドにフックを追加する方法を学びます。
依存性注入コンテナ(DIC)を使用してアプリケーションの依存関係を管理する方法を学びます。
フレームワークのコアメソッドについて学びます。
後方互換性は大部分が維持されていますが、v2からv3への移行時に認識しておくべき変更がいくつかあります。
Flightを使用する際に遭遇する可能性のある一般的な問題についてトラブルシューティングするのに役立ちます。
フレームワークをhaltメソッドを呼び出すことでいつでも停止できます:
halt
Flight::halt();
オプションでHTTPステータスコードとメッセージを指定することもできます:
HTTP
Flight::halt(200, 'Be right back...');
haltを呼び出すと、その時点までのレスポンスコンテンツが破棄されます。フレームワークを停止して現在のレスポンスを出力するには、stopメソッドを使用してください:
stop
Flight::stop();
Flight によってすべてのエラーや例外がキャッチされ、error メソッドに渡されます。 デフォルトの動作は、いくつかのエラー情報を含む汎用 HTTP 500 内部サーバーエラー 応答を送信することです。
error
HTTP 500 内部サーバーエラー
独自のニーズに合わせてこの動作を上書きすることができます:
Flight::map('error', function (Throwable $error) { // エラーを処理する echo $error->getTraceAsString(); });
デフォルトでは、エラーはウェブサーバーに記録されません。これを有効にすることでログを取得できます:
Flight::set('flight.log_errors', true);
URL が見つからない場合、Flight は notFound メソッドを呼び出します。デフォルトの動作は、簡単なメッセージを含む HTTP 404 Not Found 応答を送信することです。
notFound
HTTP 404 Not Found
Flight::map('notFound', function () { // 見つからない場合の処理 });
Laravel は、すべての機能が備わっており、素晴らしい開発者向けエコシステムを持つフル機能のフレームワークですが、パフォーマンスと複雑さにはコストがかかります。 Laravelの目標は、開発者が最高レベルの生産性を持ち、一般的なタスクを簡単に行えるようにすることです。 Laravelは、フル機能のエンタープライズ Web アプリケーションを構築しようとしている開発者にとって優れた選択肢です。 これには、パフォーマンスと複雑さの観点でいくつかのトレードオフが伴います。 Laravelの基本を学ぶことは簡単ですが、フレームワークを習得するには時間がかかるかもしれません。
開発者がしばしば問題を解決する唯一の方法はこれらのモジュールであるかのように感じるほど、Laravelモジュールが非常に多いですが、実際には別のライブラリを使用するか、独自のコードを書くこともできます。
ほとんどの場合、下位互換性は維持されていますが、v2からv3に移行する際に注意すべき変更がいくつかあります。
出力バッファリングは、PHPスクリプトによって生成された出力がクライアントに送信される前にバッファー(PHP内部)に保存されるプロセスです。これにより、出力をクライアントに送信する前に変更できます。
MVCアプリケーションでは、コントローラーが「マネージャー」であり、ビューの動作を管理します。コントローラーの外部(またはFlightの場合、時々無名関数内)で生成された出力は、MVCパターンを壊します。この変更は、MVCパターンにより準拠し、フレームワークを予測可能かつ使いやすくするためです。
v2では、出力バッファリングは、自身の出力バッファーを一貫してクローズしていなかったため、ユニットテストやストリーミングが困難になることがありました。ほとんどのユーザーにとって、この変更は実際には影響しないかもしれません。ただし、コールバックやコントローラーの外部でコンテンツをエコーしている場合(例えば、フック内で)、問題が発生する可能性があります。フック内やフレームワークの実際の実行より前にコンテンツをエコーしても、過去には動作していたかもしれませんが、今後は動作しません。
// index.php require 'vendor/autoload.php'; // just an example define('START_TIME', microtime(true)); function hello() { echo 'Hello World'; } Flight::map('hello', 'hello'); Flight::after('hello', function(){ // this will actually be fine echo '<p>This Hello World phrase was brought to you by the letter "H"</p>'; }); Flight::before('start', function(){ // things like this will cause an error echo '<html><head><title>My Page</title></head><body>'; }); Flight::route('/', function(){ // this is actually just fine echo 'Hello World'; // This should be just fine as well Flight::hello(); }); Flight::after('start', function(){ // this will cause an error echo '<div>Your page loaded in '.(microtime(true) - START_TIME).' seconds</div></body></html>'; });
古いコードを修正せずにv3で機能させるためにはどうすればよいですか? はい、できます! flight.v2.output_buffering構成オプションをtrueに設定することで、v2のレンダリング動作を有効にできます。これにより、古いレンダリング動作を継続して使用できますが、将来の修正が推奨されています。 フレームワークのv4では、これが削除されます。
flight.v2.output_buffering
true
// index.php require 'vendor/autoload.php'; Flight::set('flight.v2.output_buffering', true); Flight::before('start', function(){ // Now this will be just fine echo '<html><head><title>My Page</title></head><body>'; }); // more code
Dispatcher::invokeMethod()、Dispatcher::execute()などのDispatcherの静的メソッドを直接呼び出している場合、Dispatcherがよりオブジェクト指向に変換されたため、これらのメソッドを直接呼び出さないようにコードを更新する必要があります。 依存性注入コンテナをより簡単に使用できるようにDispatcherが変更されました。 Dispatcherと同様のメソッドを呼び出す必要がある場合は、手動で$result = $class->$method(...$params);またはcall_user_func_array()のようなものを使用することができます。
Dispatcher::invokeMethod()
Dispatcher::execute()
Dispatcher
$result = $class->$method(...$params);
call_user_func_array()
halt()
stop()
redirect()
error()
3.10.0以前のデフォルト動作は、ヘッダーとレスポンスボディの両方をクリアすることでした。これは、レスポンスボディのみをクリアするように変更されました。ヘッダーもクリアする必要がある場合は、Flight::response()->clear()を使用できます。
Flight::response()->clear()
set メソッドを使用して、Flight の特定の動作をカスタマイズできます。
set
以下は利用可能な設定の一覧です:
?string
bool
string
Content-Length
_ をクラス名に含める場合の追加のローダーの設定があります。これにより、クラスを自動的に読み込むことができます。
_
// アンダースコアを使用したクラスのローディングを有効にする // デフォルトは true Loader::$v2ClassLoading = false;
Flight を使用すると、アプリケーション内のどこからでも使用できるように変数を保存できます。
// 変数を保存する Flight::set('id', 123); // アプリケーション内の別の場所で $id = Flight::get('id');
変数が設定されているかどうかを確認するには、次のようにします:
if (Flight::has('id')) { // 何かを行う }
次のようにして変数をクリアできます:
// id 変数をクリアする Flight::clear('id'); // すべての変数をクリア Flight::clear();
Flight は設定目的で変数も使用します。
すべてのエラーと例外は Flight によってキャッチされ、error メソッドに渡されます。デフォルトの動作は、一般的な HTTP 500 Internal Server Error 応答を送信し、いくつかのエラー情報を含めることです。
HTTP 500 Internal Server Error
独自のニーズに合わせてこの動作をオーバーライドできます:
デフォルトでは、エラーはウェブサーバーにログ記録されていません。これを有効にできます:
Flight::map('notFound', function () { // 見つからなかった時の処理 });
セキュリティはWebアプリケーションに関連する重要な要素です。アプリケーションが安全であり、ユーザーのデータが保護されていることを確認したいですね。Flight はウェブアプリケーションをセキュアにするための機能をいくつか提供しています。
HTTPヘッダーはウェブアプリケーションをセキュアにする最も簡単な方法の一つです。ヘッダーを使用してクリックジャッキング、XSS、その他の攻撃を防ぐことができます。これらのヘッダーをアプリケーションに追加する方法にはいくつかの方法があります。
セキュリティヘッダーを確認するための優れたウェブサイトのいくつかは、securityheaders.com と observatory.mozilla.org です。
Flight\Response オブジェクトの header メソッドを使用してこれらのヘッダーを手動で追加できます。
Flight\Response
header
// クリックジャッキングを防ぐために X-Frame-Options ヘッダーを設定する Flight::response()->header('X-Frame-Options', 'SAMEORIGIN'); // XSS を防ぐために Content-Security-Policy ヘッダーを設定する // 注: このヘッダーは非常に複雑になる可能性があるため、 // アプリケーション用のインターネット上の例を確認することをお勧めします Flight::response()->header("Content-Security-Policy", "default-src 'self'"); // XSS を防ぐために X-XSS-Protection ヘッダーを設定する Flight::response()->header('X-XSS-Protection', '1; mode=block'); // MIME スニッフィングを防ぐために X-Content-Type-Options ヘッダーを設定する Flight::response()->header('X-Content-Type-Options', 'nosniff'); // リファラーポリシー ヘッダーを設定して送信するリファラー情報の量を制御する Flight::response()->header('Referrer-Policy', 'no-referrer-when-downgrade'); // HTTPS を強制するために Strict-Transport-Security ヘッダーを設定する Flight::response()->header('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload'); // 使用可能な機能やAPIを制御するために Permissions-Policy ヘッダーを設定する Flight::response()->header('Permissions-Policy', 'geolocation=()');
これらは bootstrap.php または index.php ファイルの先頭に追加することができます。
bootstrap.php
index.php
以下のように、フィルター/フックにこれらを追加することもできます。
// フィルター内でヘッダーを追加 Flight::before('start', function() { Flight::response()->header('X-Frame-Options', 'SAMEORIGIN'); Flight::response()->header("Content-Security-Policy", "default-src 'self'"); Flight::response()->header('X-XSS-Protection', '1; mode=block'); Flight::response()->header('X-Content-Type-Options', 'nosniff'); Flight::response()->header('Referrer-Policy', 'no-referrer-when-downgrade'); Flight::response()->header('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload'); Flight::response()->header('Permissions-Policy', 'geolocation=()'); });
ミドルウェアクラスとしても追加できます。これはコードを清潔で整理された状態に保つのに適した方法です。
// app/middleware/SecurityHeadersMiddleware.php namespace app\middleware; class SecurityHeadersMiddleware { public function before(array $params): void { Flight::response()->header('X-Frame-Options', 'SAMEORIGIN'); Flight::response()->header("Content-Security-Policy", "default-src 'self'"); Flight::response()->header('X-XSS-Protection', '1; mode=block'); Flight::response()->header('X-Content-Type-Options', 'nosniff'); Flight::response()->header('Referrer-Policy', 'no-referrer-when-downgrade'); Flight::response()->header('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload'); Flight::response()->header('Permissions-Policy', 'geolocation=()'); } } // index.php またはルートがある場所 // この空のグループは、すべてのルートに対するグローバルミドルウェアとして機能します。もちろん、同じことをして、特定のルートにのみこれを追加することもできます。 Flight::group('', function(Router $router) { $router->get('/users', [ 'UserController', 'getUsers' ]); // 他のルート }, [ new SecurityHeadersMiddleware() ]);
クロスサイトリクエストフォージェリ(CSRF)は、悪意のあるウェブサイトがユーザーのブラウザを使用してあなたのウェブサイトにリクエストを送信する攻撃の一種です。これにより、ユーザーの知識を得ることなくウェブサイトでのアクションを実行することができます。Flight はビルトインのCSRF保護メカニズムを提供していませんが、ミドルウェアを使用して簡単に独自の実装ができます。
まず、CSRFトークンを生成し、ユーザーのセッションに保存する必要があります。その後、このトークンをフォームで使用し、フォームが送信された際に確認できます。
// CSRFトークンを生成し、ユーザーのセッションに保存します // (Flight にセッションオブジェクトを作成してアタッチしていると仮定しています) // 詳細はセッションのドキュメントを参照してください Flight::register('session', \Ghostff\Session\Session::class); // セッションごとに1つのトークンを生成するだけで十分です(同じユーザーの複数のタブとリクエストで機能するようになります) if(Flight::session()->get('csrf_token') === null) { Flight::session()->set('csrf_token', bin2hex(random_bytes(32)) ); }
<!-- フォーム内でCSRFトークンを使用 --> <form method="post"> <input type="hidden" name="csrf_token" value="<?= Flight::session()->get('csrf_token') ?>"> <!-- 他のフォームフィールド --> </form>
カスタム関数を設定して、Latteテンプレート内でCSRFトークンを出力することもできます。
// CSRFトークンを出力するカスタム関数を設定 // 注: ビューはビューエンジンとしてLatteが設定されていると想定しています Flight::view()->addFunction('csrf', function() { $csrfToken = Flight::session()->get('csrf_token'); return new \Latte\Runtime\Html('<input type="hidden" name="csrf_token" value="' . $csrfToken . '">'); });
そして、Latteテンプレートでは csrf() 関数を使用してCSRFトークンを出力できます。
csrf()
<form method="post"> {csrf()} <!-- 他のフォームフィールド --> </form>
簡単ですね?
イベントフィルターを使用してCSRFトークンを確認できます:
// このミドルウェアはリクエストがPOSTリクエストかどうかを確認し、POSTリクエストの場合はCSRFトークンが有効かどうかを確認します Flight::before('start', function() { if(Flight::request()->method == 'POST') { // フォーム値からcsrfトークンを取得 $token = Flight::request()->data->csrf_token; if($token !== Flight::session()->get('csrf_token')) { Flight::halt(403, 'Invalid CSRF token'); // または JSON応答用 Flight::jsonHalt(['error' => 'Invalid CSRF token'], 403); } } });
または、ミドルウェアクラスを使用できます:
// app/middleware/CsrfMiddleware.php namespace app\middleware; class CsrfMiddleware { public function before(array $params): void { if(Flight::request()->method == 'POST') { $token = Flight::request()->data->csrf_token; if($token !== Flight::session()->get('csrf_token')) { Flight::halt(403, 'Invalid CSRF token'); } } } } // index.php またはルートがある場所 Flight::group('', function(Router $router) { $router->get('/users', [ 'UserController', 'getUsers' ]); // 他のルート }, [ new CsrfMiddleware() ]);
クロスサイトスクリプティング(XSS)は、悪意のあるウェブサイトがあなたのウェブサイトにコードをインジェクションする攻撃の一種です。これらの機会のほとんどは、エンドユーザーが記入するフォーム値から来ます。ユーザーからの出力を決して信用しないでください!常にすべてのユーザーが世界で最高のハッカーであると仮定してください。彼らは悪意のあるJavaScriptやHTMLをページにインジェクションすることができます。このコードは、ユーザーから情報を盗むか、あなたのウェブサイトでアクションを実行するために使用される可能性があります。Flightのビュークラスを使用すると、XSS攻撃を防ぐために出力を簡単にエスケープできます。
// ユーザーが賢いことを考えて、これを名前として使用しようとします $name = '<script>alert("XSS")</script>'; // この部分は出力をエスケープします Flight::view()->set('name', $name); // これが出力されます:<script>alert("XSS")</script> // ビュークラスとして設定されているLatteなどを使用している場合、これも自動的にエスケープされます。 Flight::view()->render('template', ['name' => $name]);
SQLインジェクションは、悪意のあるユーザーがSQLコードをデータベースにインジェクションできる攻撃の一種です。これを使用してデータベースから情報を盗むか、データベースでアクションを実行できます。再度、ユーザーからの入力を決して信頼しないでください!常に彼らが自衛に出ていると仮定してください。PDO オブジェクト内でプリペアステートメントを使用することで、SQLインジェクションを防げます。
PDO
// Flight::db() をPDOオブジェクトとして登録していると仮定します $statement = Flight::db()->prepare('SELECT * FROM users WHERE username = :username'); $statement->execute([':username' => $username]); $users = $statement->fetchAll(); // PdoWrapperクラスを使用して、これは簡単に1行で行うことができます $users = Flight::db()->fetchAll('SELECT * FROM users WHERE username = :username', [ 'username' => $username ]); // ?プレースホルダを使用してPDOオブジェクトで同じことができます $statement = Flight::db()->fetchAll('SELECT * FROM users WHERE username = ?', [ $username ]); // 決してこのようなことをしないでください... $users = Flight::db()->fetchAll("SELECT * FROM users WHERE username = '{$username}' LIMIT 5"); // なぜならば $username = "' OR 1=1; -- "; の場合、どうなるでしょう... // クエリが組み立てられると次のようになります // SELECT * FROM users WHERE username = '' OR 1=1; -- LIMIT 5 // 奇妙に見えるかもしれませんが、これは動作する有効なクエリです。実際、 // これは非常に一般的なSQLインジェクション攻撃で、すべてのユーザーを返します。
クロスオリジンリソース共有(CORS)は、ウェブページ上の多くのリソース(フォント、JavaScriptなど)を、リソースが起源となるドメイン以外のドメインからリクエストできるようにする仕組みです。Flight には組み込みの機能がありませんが、Flight::start() メソッドが呼び出される前にフックを実行するためのフックを簡単に設定できます。
Flight::start()
// app/utils/CorsUtil.php namespace app\utils; class CorsUtil { public function set(array $params): void { $request = Flight::request(); $response = Flight::response(); if ($request->getVar('HTTP_ORIGIN') !== '') { $this->allowOrigins(); $response->header('Access-Control-Allow-Credentials', 'true'); $response->header('Access-Control-Max-Age', '86400'); } if ($request->method === 'OPTIONS') { if ($request->getVar('HTTP_ACCESS_CONTROL_REQUEST_METHOD') !== '') { $response->header( 'Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD' ); } if ($request->getVar('HTTP_ACCESS_CONTROL_REQUEST_HEADERS') !== '') { $response->header( "Access-Control-Allow-Headers", $request->getVar('HTTP_ACCESS_CONTROL_REQUEST_HEADERS') ); } $response->status(200); $response->send(); exit; } } private function allowOrigins(): void { // ここで許可されるホストをカスタマイズしてください。 $allowed = [ 'capacitor://localhost', 'ionic://localhost', 'http://localhost', 'http://localhost:4200', 'http://localhost:8080', 'http://localhost:8100', ]; $request = Flight::request(); if (in_array($request->getVar('HTTP_ORIGIN'), $allowed, true) === true) { $response = Flight::response(); $response->header("Access-Control-Allow-Origin", $request->getVar('HTTP_ORIGIN')); } } } // index.php またはルートがある場所 $CorsUtil = new CorsUtil(); // start が実行される前にこれを実行する必要があります。 Flight::before('start', [ $CorsUtil, 'setupCors' ]);
セキュリティは重要な要素であり、Webアプリケーションが安全であることを確認することが重要です。Flight はウェブアプリケーションをセキュアにするためのいくつかの機能を提供していますが、常に用心深く、ユーザーのデータを安全に保つためにできる限りのことを行っていることを確認することが重要です。常に最悪を想定し、ユーザーからの入力を信頼せずに、出力をエスケープし、SQLインジェクションを防ぐためにプリペアドステートメントを使用してください。CSRFとCORS攻撃からルートを保護するためにミドルウェアを使用してください。これらのすべてを行うことで、安全なウェブアプリケーションの構築に向けて大きく前進することができます。
Flightは、コードを変更することなく、独自のニーズに合わせてデフォルトの機能をオーバーライドできるようにします。
たとえば、FlightがURLをルートにマッチさせられない場合、notFoundメソッドが呼び出され、一般的な HTTP 404 レスポンスが送信されます。この動作を以下のようにオーバーライドできます:
HTTP 404
Flight::map('notFound', function() { // カスタム404ページを表示 include 'errors/404.html'; });
Flightはまた、フレームワークのコアコンポーネントを置換することを許可します。 たとえば、デフォルトのRouterクラスを独自のカスタムクラスで置き換えることができます:
// カスタムクラスを登録 Flight::register('router', MyRouter::class); // FlightがRouterインスタンスをロードするとき、あなたのクラスがロードされます $myrouter = Flight::router();
mapやregisterなどのフレームワークのメソッドはオーバーライドできません。これを試みるとエラーが発生します。
map
register
Note: ルーティングについてさらに理解したいですか? より詳しい説明については、"なぜフレームワークを使うのか?" ページを参照してください。
Flight における基本的なルーティングは、URL パターンとコールバック関数またはクラスとメソッドの配列との一致によって行われます。
Flight::route('/', function(){ echo 'hello world!'; });
ルートは定義された順番で一致します。リクエストに一致する最初のルートが実行されます。
コールバックは呼び出し可能な任意のオブジェクトを使用できます。よって、通常の関数を使用できます:
function hello() { echo 'hello world!'; } Flight::route('/', 'hello');
クラスの静的メソッドを使用することもできます:
class Greeting { public static function hello() { echo 'hello world!'; } } Flight::route('/', [ 'Greeting','hello' ]);
また、最初にオブジェクトを作成してからメソッドを呼び出すこともできます:
// Greeting.php class Greeting { public function __construct() { $this->name = 'John Doe'; } public function hello() { echo "Hello, {$this->name}!"; } } // index.php $greeting = new Greeting(); Flight::route('/', [ $greeting, 'hello' ]); // オブジェクトを作成せずにこれを行うこともできます // 注意:引数はコンストラクタに注入されません Flight::route('/', [ 'Greeting', 'hello' ]); // さらに、この短縮構文を使用することもできます Flight::route('/', 'Greeting->hello'); // または Flight::route('/', Greeting::class.'->hello');
コンテナ(PSR-11、PHP-DI、Dice など)を使った依存性の注入を行いたい場合、 依存性の注入を使用できる唯一のタイプのルートは、オブジェクトを直接作成して自分自身でオブジェクトを作成するコンテナを使用するか、クラスとメソッドを呼び出すために文字列を使用するルートです。詳細についてはDependency Injection ページを参照してください。
以下に簡単な例を示します:
use flight\database\PdoWrapper; // Greeting.php class Greeting { protected PdoWrapper $pdoWrapper; public function __construct(PdoWrapper $pdoWrapper) { $this->pdoWrapper = $pdoWrapper; } public function hello(int $id) { // $this->pdoWrapper を使って何かをします $name = $this->pdoWrapper->fetchField("SELECT name FROM users WHERE id = ?", [ $id ]); echo "こんにちは、世界! 私の名前は {$name} です!"; } } // index.php // 必要なパラメータを使用してコンテナを設定します // PSR-11 の詳細については、Dependency Injection ページを参照してください $dice = new \Dice\Dice(); // 忘れずに変数を `$dice= ` で再割り当てしてください!!!! $dice = $dice->addRule('flight\database\PdoWrapper', [ 'shared' => true, 'constructParams' => [ 'mysql:host=localhost;dbname=test', 'root', 'password' ] ]); // コンテナハンドラを登録します Flight::registerContainerHandler(function($class, $params) use ($dice) { return $dice->create($class, $params); }); // 通常通りルートを設定します Flight::route('/hello/@id', [ 'Greeting', 'hello' ]); // または Flight::route('/hello/@id', 'Greeting->hello'); // または Flight::route('/hello/@id', 'Greeting::hello'); Flight::start();
デフォルトでは、ルートパターンはすべてのリクエストメソッドと一致します。特定のメソッドに応答することができます リクエストを URL の前に識別子を置くことで。
Flight::route('GET /', function () { echo 'GET リクエストを受け取りました。'; }); Flight::route('POST /', function () { echo 'POST リクエストを受け取りました。'; }); // ルートを作成するために Flight::get() を使用することはできません // これはルートを作成するのではなく、変数を取得するためのメソッドです。 // Flight::post('/', function() { /* コード */ }); // Flight::patch('/', function() { /* コード */ }); // Flight::put('/', function() { /* コード */ }); // Flight::delete('/', function() { /* コード */ });
| デリミタを使用して複数のメソッドを単一のコールバックにマップすることもできます:
|
Flight::route('GET|POST /', function () { echo 'GET または POST リクエストを受け取りました。'; });
さらに、使用するヘルパーメソッドがいくつか含まれている Router オブジェクトを取得できます:
$router = Flight::router(); // すべてのメソッドにマップします $router->map('/', function() { echo 'hello world!'; }); // GET リクエスト $router->get('/users', function() { echo 'users'; }); // $router->post(); // $router->put(); // $router->delete(); // $router->patch();
ルートで正規表現を使用できます:
Flight::route('/user/[0-9]+', function () { // これは /user/1234 に一致します });
このメソッドは利用可能ですが、名前付きパラメータまたは正規表現付きの名前付きパラメータを使用することが推奨されています。それらはより読みやすく維持しやすいです。
コールバック関数で使用する名前付きパラメータを指定できます。
Flight::route('/@name/@id', function (string $name, string $id) { echo "$name ($id) さん、こんにちは!"; });
: デリミタを使用して名前付きパラメータに正規表現を含めることもできます:
:
Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { // これは /bob/123 に一致します // ただし /bob/12345 には一致しません });
Note: 名前付きパラメータで正規表現のグループ () に一致させることはサポートされていません。 :'(
()
一致させるためにオプションの名前付きパラメータを指定できます。一致しないオプションのパラメータは NULL として渡されます。
NULL
Flight::route( '/blog(/@year(/@month(/@day)))', function(?string $year, ?string $month, ?string $day) { // 以下の URL に一致します: // /blog/2012/12/10 // /blog/2012/12 // /blog/2012 // /blog } );
一致は個々の URL セグメントでのみ行われます。複数のセグメントに一致させたい場合は、* ワイルドカードを使用できます。
*
Flight::route('/blog/*', function () { // これは /blog/2000/02/01 に一致します });
すべてのリクエストを単一のコールバックにルーティングする場合は、次のようにします:
Flight::route('*', function () { // 何かをします });
コールバック関数から true を返すことで、次に一致するルートに実行を渡すことができます。
Flight::route('/user/@name', function (string $name) { // ある条件を確認 if ($name !== "Bob") { // 次のルートに続行 return true; } }); Flight::route('/user/*', function () { // これが呼ばれます });
ルートにエイリアスを割り当てることで、URL を後で動的に生成できます(たとえば、テンプレートなど)。
Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); // あとでどこかのコードで Flight::getUrl('user_view', [ 'id' => 5 ]); // '/users/5' を返します
あなたの URL が変更された場合、ルートエイリアスを使用すると、エイリアスを参照している場所全てを変更する必要がありません。 上記の例のように、ユーザーが /admin/users/@id に移動した場合、エイリアスを使用している場所全てを変更する必要はないため、エイリアスが非常に役立ちます。
/admin/users/@id
ルートのエイリアスはグループ内でも機能します:
Flight::group('/users', function() { Flight::route('/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); }); // あとでどこかのコードで Flight::getUrl('user_view', [ 'id' => 5 ]); // '/users/5' を返します
一致するルート情報を検査したい場合は、ルートメソッドの第三引数として true を渡すことで、ルートオブジェクトをコールバック関数に渡すように要求することができます。 ルートオブジェクトはいつもコールバック関数に渡される最後のパラメータになります。
Flight::route('/', function(\flight\net\Route $route) { // 一致した HTTP メソッドの配列 $route->methods; // 名前付きパラメータの配列 $route->params; // 一致した正規表現 $route->regex; // URL パターン内で使用されている '*' の内容 $route->splat; // URL パターンを表示します... 必要な場合は... $route->pattern; // このルートに割り当てられたミドルウェアを表示します $route->middleware; // このルートに割り当てられたエイリアスを表示します $route->alias; }, true);
関連するルートをまとめたい場合(たとえば、/api/v1 など)、group メソッドを使用できます:
/api/v1
group
Flight::group('/api/v1', function () { Flight::route('/users', function () { // /api/v1/users に一致 }); Flight::route('/posts', function () { // /api/v1/posts に一致 }); });
グループのグループをネストさせることもできます:
Flight::group('/api', function () { Flight::group('/v1', function () { // Flight::get() は変数を取得しますが、ルートを設定するわけではありません! オブジェクトコンテキストを参照してください Flight::route('GET /users', function () { // GET /api/v1/users に一致 }); Flight::post('/posts', function () { // POST /api/v1/posts に一致 }); Flight::put('/posts/1', function () { // PUT /api/v1/posts に一致 }); }); Flight::group('/v2', function () { // Flight::get() は変数を取得しますが、ルートを設定するわけではありません! オブジェクトコンテキストを参照してください Flight::route('GET /users', function () { // GET /api/v2/users に一致 }); }); });
次のように、Engine オブジェクトを使用してルートグループ化を行うことができます:
Engine
$app = new \flight\Engine(); $app->group('/api/v1', function (Router $router) { // $router 変数を使用してください $router->get('/users', function () { // GET /api/v1/users に一致 }); $router->post('/posts', function () { // POST /api/v1/posts に一致 }); });
streamWithHeaders() メソッドを使用して、クライアントに対して応答をストリーミングで送信することができます。 これは大きなファイル、長時間実行されるプロセス、または大規模な応答を生成する場合に役立ちます。 ルートをストリーミングする場合、通常のルートよりもやや異なる方法で処理されます。
streamWithHeaders()
注意: flight.v2.output_buffering が false に設定されている場合のみ、ストリーミング応答を使用できます。
ルートで stream() メソッドを使用することで、クライアントに対して応答をストリーミングすることができます。これを行う場合は、クライアントに何かを出力する前に全てのメソッドを手動で設定する必要があります。 これは header() php 関数または Flight::response()->setRealHeader() メソッドで行います。
stream()
header()
Flight::response()->setRealHeader()
Flight::route('/@filename', function($filename) { // パスをサニタイズする必要があります $fileNameSafe = basename($filename); // ルートの実行後にここに追加する追加ヘッダがある場合 // 何かをエコーする前にそれ```md # ルーティング > **注意:** ルーティングについてさらに理解したいですか? より詳しい説明については、["なぜフレームワークを使うのか?"](learn/why-frameworks) ページを参照してください。 Flight における基本的なルーティングは、URL パターンとコールバック関数またはクラスとメソッドの配列との一致によって行われます。 ```php Flight::route('/', function(){ echo 'hello world!'; });
// Greeting.php class Greeting { public function __construct() { $this->name = 'John Doe'; } public function hello() { echo "こんにちは、{$this->name}さん!"; } } // index.php $greeting = new Greeting(); Flight::route('/', [ $greeting, 'hello' ]); // オブジェクトを作成せずにこれを行うこともできます // 注意:引数はコンストラクタに注入されません Flight::route('/', [ 'Greeting', 'hello' ]); // さらに、この短縮構文を使用することもできます Flight::route('/', 'Greeting->hello'); // または Flight::route('/', Greeting::class.'->hello');
注意: 名前付きパラメータで正規表現のグループ () に一致させることはサポートされていません。 :'(
ルートエイリアスはグループ内でも機能します:
Flight::route('/@filename', function($filename) { // パスをサニタイズする必要があります $fileNameSafe = basename($filename); // ルートの実行後にここに追加する追加ヘッダがある場合 // 何かをエコーする必要があります。 ファイルのデータを取得します if(empty($fileData)) { Flight::halt(404, 'ファイルが見つかりません'); } // 必要に応じてコンテンツの長さを手動で設定します header('Content-Length: '.filesize($filename)); // データをクライアントにストリーミングします echo $fileData; // こちらが魔法の行です })->stream();
streamWithHeaders() メソッドを使用することで、ストリーミングを開始する前にヘッダーを設定することができます。
Flight::route('/stream-users', function() { // ここで好きな追加ヘッダを追加できます // header() または Flight::response()->setRealHeader() を使用する必要があります // データの取得方法は問いません、とりあえずの例... $users_stmt = Flight::db()->query("SELECT id, first_name, last_name FROM users"); echo '{'; $user_count = count($users); while($user = $users_stmt->fetch(PDO::FETCH_ASSOC)) { echo json_encode($user); if(--$user_count > 0) { echo ','; } // クライアントにデータを送信するために必要です ob_flush(); } echo '}'; // ストリーミングを開始する前にヘッダーを設定する方法 })->streamWithHeaders([ 'Content-Type' => 'application/json', 'Content-Disposition' => 'attachment; filename="users.json"', // オプショナルなステータスコード、デフォルトは 200 'status' => 200 ]);
Symfony は、再利用可能な PHP コンポーネントと、Web プロジェクト用の PHP フレームワークです。
最高の PHP アプリケーションが構築される標準基盤。独自のアプリケーションに使用できる 50 個のスタンドアロンコンポーネントのいずれかを選択してください。
PHP Web アプリケーションの作成とメンテナンスをスピードアップします。反復的なコーディングタスクを終了し、コードを制御する力を享受します。
もし、Laravel、Slim、Fat-Free、あるいはSymfonyのような他のフレームワークからFlightに移行している場合、このページは両者の違いを理解するのに役立ちます。
Laravelはベルと笛がすべて揃った充実したフレームワークで、驚くべき開発者中心のエコシステムを持っていますが、パフォーマンスと複雑さと引き換えになります。
LaravelとFlightの比較を見る.
SlimはFlightに似たマイクロフレームワークです。軽量で使いやすく設計されていますが、Flightよりも少し複雑になることがあります。
SlimとFlightの比較を見る.
Fat-Freeはより小さなパッケージで提供されるフルスタックフレームワークです。ツールはすべてそろっていますが、いくつかのプロジェクトをより複雑にするデータアーキテクチャを持っています。
Fat-FreeとFlightの比較を見る.
Symfonyはモジュール式のエンタープライズレベルのフレームワークであり、柔軟性と拡張性を備えています。より小さなプロジェクトや新人開発者にとって、Symfonyは少し抵抗があるかもしれません。
SymfonyとFlightの比較を見る.
Flight は、変数を保存してアプリケーション内のどこでも使用できるようにします。
// あなたの変数を保存する Flight::set('id', 123); // アプリケーションの別の場所で $id = Flight::get('id');
変数が設定されているかどうかを確認するには、次のようにします。
if (Flight::has('id')) { // 何かを実行 }
変数をクリアするには、次のようにします。
// id 変数をクリア Flight::clear('id'); // すべての変数をクリア Flight::clear();
依存性の注入コンテナ (DIC) は、アプリケーションの依存関係を管理する強力なツールであります。これは、現代のPHPフレームワークで重要な概念であり、オブジェクトのインスタンス化と構成を管理するために使用されます。DIC ライブラリの例には次のものがあります: Dice, Pimple, PHP-DI, および league/container。
DIC とは、クラスを中央集権的に作成および管理できるという洒落た方法です。これは、同じオブジェクトを複数のクラス (たとえば、コントローラー) に渡す必要がある場合に役立ちます。簡単な例は、この概念を理解するのに役立つでしょう。
昔は以下のように行っていたかもしれません:
// 以前の方法
以上のコードからわかるように、新しい PDO オブジェクトを作成して UserController クラスに渡しています。これは小規模なアプリケーションには適していますが、アプリケーションが成長すると、同じ PDO オブジェクトを複数箇所で作成していることがわかります。ここで DIC が役立ちます。
UserController
こちらは (Dice を使用した) DIC を使用して同じ例を示したものです:
// DIC を使用した同じ例
もしかすると、この例には多くの余分なコードが追加されたと思っているかもしれません。その魔法は、PDO オブジェクトが必要な別のコントローラーを持っている場合に来ます。
// 他のコントローラーが PDO オブジェクトが必要な場合
DIC を利用することの追加メリットは、ユニットテストがはるかに容易になることです。モックオブジェクトを作成してクラスに渡すことができます。これは、アプリケーションのテストを書く際に非常に有益です!
Flight は PSR-11 に準拠したコンテナも利用できます。これは、PSR-11 インターフェースを実装した任意のコンテナを使用できることを意味します。以下は、League の PSR-11 コンテナを使用した例です:
// PSR-11 コンテナを使用した例
この Dice の例よりも少し冗長かもしれませんが、同じ利点を持って問題なく機能します!
独自の DIC ハンドラも作成することができます。これは、PSR-11 ではないカスタムコンテナを使用したい場合に役立ちます。これを行う方法についての詳細については、基本的な例を参照してください。
さらに、Flight の使用時に生活をより簡単にするためのいくつかの便利なデフォルトがあります。
コントローラー/ミドルウェアで Engine インスタンスを使用する場合、以下のように構成できます:
// エンジンインスタンスを使用する方法
コンテナに追加したい他のクラスがある場合、Dice を使用すると自動的に解決されます。以下は例です:
// 他のクラスの追加
Flightはルートおよびグループルートのミドルウェアをサポートしています。ミドルウェアは、ルートコールバックの前(または後)に実行される関数です。これは、コード内にAPI認証チェックを追加したり、ユーザーがルートにアクセスする権限を持っていることを検証するのに便利な方法です。
基本的な例を以下に示します:
// 無名関数のみを指定する場合、ルートコールバックの前に実行されます。 // 「after」ミドルウェア関数はクラスを除いて存在しません(以下を参照) Flight::route('/path', function() { echo 'Here I am!'; })->addMiddleware(function() { echo 'Middleware first!'; }); Flight::start(); // これにより、「Middleware first! Here I am!」と表示されます。
ミドルウェアについて重要な注意事項がいくつかありますので、使用する前に認識しておく必要があります:
Flight::redirect()
function($params) { ... }
public function before($params) {}
__construct()
flight\Engine
ミドルウェアはクラスとしても登録できます。"after"機能が必要な場合は、必ずクラスを使用する必要があります。
class MyMiddleware { public function before($params) { echo 'Middleware first!'; } public function after($params) { echo 'Middleware last!'; } } $MyMiddleware = new MyMiddleware(); Flight::route('/path', function() { echo 'Here I am! '; })->addMiddleware($MyMiddleware); // または ->addMiddleware([ $MyMiddleware, $MyMiddleware2 ]); Flight::start(); // これにより、「Middleware first! Here I am! Middleware last!」が表示されます。
認証ミドルウェアがあるとして、認証されていない場合にユーザーをログインページにリダイレクトしたいとします。その場合、次のオプションがいくつかあります:
次に、単純なfalseを返す例を示します:
class MyMiddleware { public function before($params) { if (isset($_SESSION['user']) === false) { return false; } // trueであるため、すべてが進行し続けます } }
ユーザーをログインページにリダイレクトする例は次のとおりです:
class MyMiddleware { public function before($params) { if (isset($_SESSION['user']) === false) { Flight::redirect('/login'); exit; } } }
APIを構築しているため、JSONエラーをスローする必要があるとしましょう。これは以下のように行えます:
class MyMiddleware { public function before($params) { $authorization = Flight::request()->headers['Authorization']; if(empty($authorization)) { Flight::jsonHalt(['error' => 'You must be logged in to access this page.'], 403); // または Flight::json(['error' => 'You must be logged in to access this page.'], 403); exit; // または Flight::halt(403, json_encode(['error' => 'You must be logged in to access this page.']); } } }
ルートグループを追加し、そのグループ内のすべてのルートに同じミドルウェアを適用できます。これは、例えばヘッダーのAPIキーをチェックするために、多くのルートをグループ化する必要がある場合に便利です。
// グループメソッドの最後に追加 Flight::group('/api', function() { // この「空」に見えるルートは実際には/apiに一致します Flight::route('', function() { echo 'api'; }, false, 'api'); // これは/api/usersに一致します Flight::route('/users', function() { echo 'users'; }, false, 'users'); // これは/api/users/1234に一致します Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); }, [ new ApiAuthMiddleware() ]);
すべてのルートにグローバルミドルウェアを適用する場合は、次のようにして「空の」グループを追加できます:
// グループメソッドの最後に追加 Flight::group('', function() { // これは依然として/usersです Flight::route('/users', function() { echo 'users'; }, false, 'users'); // そしてこれは依然として/users/1234です Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); }, [ new ApiAuthMiddleware() ]);
Flightは、メソッドが呼び出される前後にフィルタリングを行うことができます。覚える必要のある事前定義されたフックはありません。デフォルトのフレームワークメソッドやマップしたカスタムメソッドのいずれに対してもフィルタリングを行うことができます。
フィルタ関数は次のようになります:
function (array &$params, string &$output): bool { // フィルタコード }
渡された変数を使用して、入力パラメータや出力を操作することができます。
メソッドの前にフィルタを実行するには、次のようにします:
Flight::before('start', function (array &$params, string &$output): bool { // 何かを行う });
メソッドの後にフィルタを実行するには、次のようにします:
Flight::after('start', function (array &$params, string &$output): bool { // 何かを行う });
任意のメソッドに複数のフィルタを追加することができます。宣言された順序通りに呼び出されます。
以下はフィルタリングプロセスの例です:
// カスタムメソッドをマップ Flight::map('hello', function (string $name) { return "Hello, $name!"; }); // フィルタを追加 Flight::before('hello', function (array &$params, string &$output): bool { // パラメータを操作する $params[0] = 'Fred'; return true; }); // フィルタを追加 Flight::after('hello', function (array &$params, string &$output): bool { // 出力を操作する $output .= " Have a nice day!"; return true; }); // カスタムメソッドを呼び出す echo Flight::hello('Bob');
これにより次のように表示されます:
Hello Fred! Have a nice day!
複数のフィルタを定義している場合は、フィルタ関数のいずれかで false を返すことで、チェーンを中断することができます:
false
Flight::before('start', function (array &$params, string &$output): bool { echo 'one'; return true; }); Flight::before('start', function (array &$params, string &$output): bool { echo 'two'; // これによりチェーンが終了します return false; }); // これは呼び出されません Flight::before('start', function (array &$params, string &$output): bool { echo 'three'; return true; });
map や register などのコアメソッドは、直接呼び出されて動的に呼び出されないため、フィルタリングすることはできません。
FlightはHTTPリクエストを単一のオブジェクトにカプセル化し、 次のようにアクセスできます:
$request = Flight::request();
Webアプリケーションでリクエストを処理する際は、通常、ヘッダーを 取り出したり、$_GETや$_POSTのパラメータを取得したり、あるいは 生のリクエストボディを取得したいと思うことでしょう。Flightはそれを 簡単に行うためのインターフェースを提供します。
$_GET
$_POST
クエリ文字列パラメータを取得する例は以下の通りです:
Flight::route('/search', function(){ $keyword = Flight::request()->query['keyword']; echo "あなたが検索しているのは: $keyword"; // $keywordを使ってデータベースにクエリするか、何か他のことをする });
POSTメソッドのフォームの例はこちらです:
Flight::route('POST /submit', function(){ $name = Flight::request()->data['name']; $email = Flight::request()->data['email']; echo "あなたが送信したのは: $name, $email"; // $nameと$emailを使ってデータベースに保存するか、何か他のことをする });
リクエストオブジェクトは以下のプロパティを提供します:
HTTP_CLIENT_IP
HTTP_X_FORWARDED_FOR
HTTP_X_FORWARDED
HTTP_X_CLUSTER_CLIENT_IP
HTTP_FORWARDED_FOR
HTTP_FORWARDED
$_SERVER
query、data、cookies、およびfilesプロパティには 配列またはオブジェクトとしてアクセスできます。
query
data
cookies
files
したがって、クエリ文字列パラメータを取得するには、次のようにできます:
$id = Flight::request()->query['id'];
または、次のようにできます:
$id = Flight::request()->query->id;
例えばPUTリクエストを扱うときに生のHTTPリクエストボディを取得するには、
$body = Flight::request()->getBody();
application/jsonタイプのリクエストでデータ{"id": 123}を送信すると、 それはdataプロパティから利用可能になります:
application/json
{"id": 123}
$id = Flight::request()->data->id;
$_GET配列にはqueryプロパティを介してアクセスできます:
$_POST配列にはdataプロパティを介してアクセスできます:
$id = Flight::request()->data['id'];
$_COOKIE
$_COOKIE配列にはcookiesプロパティを介してアクセスできます:
$myCookieValue = Flight::request()->cookies['myCookieName'];
$_SERVER配列にはgetVar()メソッドを介してショートカットでアクセスできます:
getVar()
$host = Flight::request()->getVar['HTTP_HOST'];
$_FILES
filesプロパティを介してアップロードされたファイルにアクセスできます:
$uploadedFile = Flight::request()->files['myFile'];
フレームワークを使用してファイルアップロードを処理できます。基本的には リクエストからファイルデータを取り出し、それを新しい場所に移動することです。
Flight::route('POST /upload', function(){ // <input type="file" name="myFile">のような入力フィールドがあった場合 $uploadedFileData = Flight::request()->getUploadedFiles(); $uploadedFile = $uploadedFileData['myFile']; $uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename()); });
複数のファイルがアップロードされている場合は、それらをループ処理できます:
Flight::route('POST /upload', function(){ // <input type="file" name="myFiles[]">のような入力フィールドがあった場合 $uploadedFiles = Flight::request()->getUploadedFiles()['myFiles']; foreach ($uploadedFiles as $uploadedFile) { $uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename()); } });
セキュリティノート: ユーザー入力を常に検証し、サニタイズしてください。特にファイルアップロードを扱う場合は注意が必要です。許可する拡張子のタイプを必ず検証し、ファイルが実際にユーザーが主張するファイルタイプであることを確認するために「マジックバイト」も検証してください。これに役立つ記事、および、ライブラリがあります。
getHeader()またはgetHeaders()メソッドを使用してリクエストヘッダーにアクセスできます:
getHeader()
getHeaders()
// おそらくAuthorizationヘッダーが必要な場合 $host = Flight::request()->getHeader('Authorization'); // または $host = Flight::request()->header('Authorization'); // すべてのヘッダーを取得する必要がある場合 $headers = Flight::request()->getHeaders(); // または $headers = Flight::request()->headers();
getBody()メソッドを使用して生のリクエストボディにアクセスできます:
getBody()
methodプロパティまたはgetMethod()メソッドを使用してリクエストメソッドにアクセスできます:
method
getMethod()
$method = Flight::request()->method; // 実際にはgetMethod()を呼び出す $method = Flight::request()->getMethod();
注意: getMethod()メソッドは最初に$_SERVER['REQUEST_METHOD']からメソッドを取得し、その後、存在する場合は$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']によって上書きされるか、存在する場合は$_REQUEST['_method']によって上書きされることがあります。
$_SERVER['REQUEST_METHOD']
$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']
$_REQUEST['_method']
URLの部分を組み合わせるためのいくつかのヘルパーメソッドがあります。
getFullUrl()メソッドを使用して完全なリクエストURLにアクセスできます:
getFullUrl()
$url = Flight::request()->getFullUrl(); // https://example.com/some/path?foo=bar
getBaseUrl()メソッドを使用してベースURLにアクセスできます:
getBaseUrl()
$url = Flight::request()->getBaseUrl(); // 注意: トレーリングスラッシュはありません。 // https://example.com
parseQuery()メソッドにURLを渡すことで、クエリ文字列を連想配列に解析できます:
parseQuery()
$query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); // ['foo' => 'bar']
Flightは使いやすく理解しやすいように設計されています。以下はフレームワークの完全なメソッドセットです。 コアメソッドには、通常の静的メソッドであるコアメソッドと、フィルタリングやオーバーライドが可能なマップされたメソッドである拡張メソッドが含まれています。
Flight::map(string $name, callable $callback, bool $pass_route = false) // カスタムフレームワークメソッドを作成します。 Flight::register(string $name, string $class, array $params = [], ?callable $callback = null) // クラスをフレームワークメソッドに登録します。 Flight::before(string $name, callable $callback) // フレームワークメソッドの前にフィルタを追加します。 Flight::after(string $name, callable $callback) // フレームワークメソッドの後にフィルタを追加します。 Flight::path(string $path) // クラスの自動読み込み用のパスを追加します。 Flight::get(string $key) // 変数を取得します。 Flight::set(string $key, mixed $value) // 変数を設定します。 Flight::has(string $key) // 変数が設定されているかどうかを確認します。 Flight::clear(array|string $key = []) // 変数をクリアします。 Flight::init() // フレームワークをデフォルト設定に初期化します。 Flight::app() // アプリケーションオブジェクトのインスタンスを取得します。
Flight::start() // フレームワークを開始します。 Flight::stop() // フレームワークを停止してレスポンスを送信します。 Flight::halt(int $code = 200, string $message = '') // オプションのステータスコードとメッセージでフレームワークを停止します。 Flight::route(string $pattern, callable $callback, bool $pass_route = false) // URLパターンをコールバックにマップします。 Flight::group(string $pattern, callable $callback) // URLのグループを作成します。パターンは文字列でなければなりません。 Flight::redirect(string $url, int $code) // 別のURLにリダイレクトします。 Flight::render(string $file, array $data, ?string $key = null) // テンプレートファイルをレンダリングします。 Flight::error(Throwable $error) // HTTP 500レスポンスを送信します。 Flight::notFound() // HTTP 404レスポンスを送信します。 Flight::etag(string $id, string $type = 'string') // ETag HTTPキャッシュを実行します。 Flight::lastModified(int $time) // 最終変更日HTTPキャッシュを実行します。 Flight::json(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // JSONレスポンスを送信します。 Flight::jsonp(mixed $data, string $param = 'jsonp', int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // JSONPレスポンスを送信します。
mapとregisterで追加された任意のカスタムメソッドもフィルタリングできます。
# フレームワーク API メソッド Flight は使いやすく理解しやすいように設計されています。以下はフレームワークの完全なメソッドセットです。 これには、通常の静的メソッドであるコアメソッドと、フィルタリングやオーバーライドが可能なマップされたメソッドである拡張可能メソッドが含まれています。 ## コアメソッド これらのメソッドはフレームワークのコアであり、オーバーライドすることはできません。 ```php Flight::map(string $name, callable $callback, bool $pass_route = false) // カスタムフレームワークメソッドを作成します。 Flight::register(string $name, string $class, array $params = [], ?callable $callback = null) // クラスをフレームワークメソッドに登録します。 Flight::unregister(string $name) // クラスのフレームワークメソッド登録を解除します。 Flight::before(string $name, callable $callback) // フレームワークメソッドの前にフィルタを追加します。 Flight::after(string $name, callable $callback) // フレームワークメソッドの後にフィルタを追加します。 Flight::path(string $path) // クラスの自動読み込みのためのパスを追加します。 Flight::get(string $key) // Flight::set() によって設定された変数を取得します。 Flight::set(string $key, mixed $value) // Flight エンジン内で変数を設定します。 Flight::has(string $key) // 変数が設定されているかどうかを確認します。 Flight::clear(array|string $key = []) // 変数をクリアします。 Flight::init() // フレームワークをデフォルト設定に初期化します。 Flight::app() // アプリケーションオブジェクトインスタンスを取得します。 Flight::request() // リクエストオブジェクトインスタンスを取得します。 Flight::response() // レスポンスオブジェクトインスタンスを取得します。 Flight::router() // ルーターオブジェクトインスタンスを取得します。 Flight::view() // ビューオブジェクトインスタンスを取得します。
Flight::start() // フレームワークを開始します。 Flight::stop() // フレームワークを停止し、レスポンスを送信します。 Flight::halt(int $code = 200, string $message = '') // オプションのステータスコードとメッセージでフレームワークを停止します。 Flight::route(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // URL パターンをコールバックにマップします。 Flight::post(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // POST リクエストの URL パターンをコールバックにマップします。 Flight::put(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // PUT リクエストの URL パターンをコールバックにマップします。 Flight::patch(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // PATCH リクエストの URL パターンをコールバックにマップします。 Flight::delete(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // DELETE リクエストの URL パターンをコールバックにマップします。 Flight::group(string $pattern, callable $callback) // URL のグループ化を作成します。パターンは文字列である必要があります。 Flight::getUrl(string $name, array $params = []) // ルートエイリアスに基づいた URL を生成します。 Flight::redirect(string $url, int $code) // 別の URL にリダイレクトします。 Flight::download(string $filePath) // ファイルをダウンロードします。 Flight::render(string $file, array $data, ?string $key = null) // テンプレートファイルをレンダリングします。 Flight::error(Throwable $error) // HTTP 500 レスポンスを送信します。 Flight::notFound() // HTTP 404 レスポンスを送信します。 Flight::etag(string $id, string $type = 'string') // ETag HTTP キャッシュを実行します。 Flight::lastModified(int $time) // 最終変更日 HTTP キャッシュを実行します。 Flight::json(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // JSON レスポンスを送信します。 Flight::jsonp(mixed $data, string $param = 'jsonp', int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // JSONP レスポンスを送信します。 Flight::jsonHalt(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // JSON レスポンスを送信し、フレームワークを停止します。
map と register で追加されたカスタムメソッドは、フィルタリングすることもできます。 これらのメソッドをどのようにマップするかの例については、Extending Flight ガイドを参照してください。
一部のプログラマーは、フレームワークの使用に熱烈に反対しています。フレームワークは膨大で、遅く、学習が困難だと主張しています。 彼らは、フレームワークは不要であり、それらなしでより良いコードを書くことができると述べています。 フレームワークを使用することのデメリットについては、いくつかの妥当なポイントがあります。 ただし、フレームワークを使用する利点もたくさんあります。
フレームワークを使用したいと思う理由のいくつかを以下に示します:
Flightはマイクロフレームワークです。 つまり、小さく軽量です。 LaravelやSymfonyのような大規模なフレームワークほどの機能は提供しません。 ただし、Webアプリケーションを構築するために必要な機能の多くを提供します。 また、学びやすく使用も容易です。 これにより、簡単かつ迅速にWebアプリケーションを構築するのに適しています。 フレームワークに新しい場合は、Flightは初心者に最適なフレームワークです。 フレームワークを使用する利点を学び、過度な複雑さで圧倒されることなく学習するのに役立ちます。 Flightの経験を積んだ後は、LaravelやSymfonyなどのより複雑なフレームワークに移ることがより簡単になります。 ただし、Flightでも成功した堅牢なアプリケーションを作成できます。
ルーティングはFlightフレームワークの中核ですが、それは一体何でしょうか? ルーティングとは、URLを取得してコード内の特定の関数に一致させるプロセスです。 これにより、WebサイトをリクエストされたURLに基づいて異なる動作をさせることができます。 たとえば、ユーザーが/user/1234を訪れたときにユーザープロフィールを表示したいが、/usersを訪れたときに全ユーザーのリストを表示したいとします。 これはすべてルーティングを通じて行われます。
/user/1234
/users
以下のようになります:
http://example.com/user/1234
Flight::route('/user/@id', [ 'UserController', 'viewUserProfile' ]);
viewUserProfile($id)
$id
1234
viewUserProfile()
適切な中央集権的なルーターを持つことで、あなたの生活が劇的に簡単になる可能性があります! 最初はそれが見えにくいかもしれません。 以下は、そのいくつか理由です:
user_view
id
/admin/user/1234
多分、Webサイトを作成するためのスクリプトごとの方法に慣れているかもしれません。 index.phpというファイルがあり、URLを確認し、URLに基づいて特定の関数を実行します。 これもルーティングの一形態ですが、整理されていない上にすぐに手に負えなくなります。 Flightのルーティングシステムは、ルーティングを処理するより整理された強力な方法です。
これ?
// /user/view_profile.php?id=1234 if ($_GET['id']) { $id = $_GET['id']; viewUserProfile($id); } // /user/edit_profile.php?id=1234 if ($_GET['id']) { $id = $_GET['id']; editUserProfile($id); } // etc...
それともこちら?
// index.php Flight::route('/user/@id', [ 'UserController', 'viewUserProfile' ]); Flight::route('/user/@id/edit', [ 'UserController', 'editUserProfile' ]); // In maybe your app/controllers/UserController.php class UserController { public function viewUserProfile($id) { // do something } public function editUserProfile($id) { // do something } }
中央集権的なルーティングシステムを使用する利点が見え始めたことを願っています。 長い目で見れば、管理や理解が容易になります!
Flightはリクエストとレスポンスを処理するための簡単で簡単な方法を提供します。 これがWebフレームワークの中核です。 ユーザーのブラウザからのリクエストを受け取り、処理してからレスポンスを返すことで、Webアプリケーションを構築できます。 これにより、ユーザープロフィールを表示したり、ユーザーのログインを許可したり、新しいブログ投稿を許可したりするWebアプリケーションを構築できます。
リクエストは、ユーザーのブラウザがウェブサイトを訪れるときにサーバーに送信するものです。 このリクエストには、ユーザーが何をしたいかに関する情報が含まれます。 たとえば、ユーザーが訪れたいURLの情報、ユーザーがサーバーに送りたいデータ、サーバーから受け取りたいデータの種類などが含まれるかもしれません。 リクエストは読み取り専用です。 リクエストを変更することはできませんが、読み取ることはできます。
Flightはリクエストに関する情報にアクセスするための簡単な方法を提供します。 Flight::request()メソッドを使用してリクエストに関する情報にアクセスできます。 このメソッドはリクエストに関する情報を含むRequestオブジェクトを返します。 このオブジェクトを使用して、URL、メソッド、ユーザーがサーバーに送信したデータなどの情報にアクセスできます。
Flight::request()
Request
レスポンスとは、ユーザーのブラウザがウェブサイトを訪れるときにサーバーがユーザーのブラウザに送り返すものです。 このレスポンスには、サーバーが行いたいことに関する情報が含まれます。 たとえば、サーバーがユーザーに送信したいデータの種類、ユーザーから受け取りたいデータの種類、サーバーがユーザーのコンピュータに保存したいデータの種類などが含まれるかもしれません。
Flightはユーザーのブラウザにレスポンスを送信する簡単な方法を提供します。 Flight::response()メソッドを使用してレスポンスを送信できます。 このメソッドは、Responseオブジェクトを引数として受け取り、そのレスポンスをユーザーのブラウザに送信します。 このオブジェクトを使用して、HTML、JSON、ファイルなど、ユーザーのブラウザにレスポンスを送信できます。 Flightはレスポンスの一部を自動生成して簡単にするお手伝いをしますが、最終的にはユーザーに送り返す内容を制御できます。
Flight::response()
Response
Flight は HTTP レベルのキャッシングを組み込みでサポートしています。キャッシングの条件を満たすと、Flight は HTTP 304 Not Modified のレスポンスを返します。クライアントが同じリソースを次にリクエストするときは、ローカルにキャッシュされたバージョンを使用するよう促されます。
304 Not Modified
lastModified メソッドを使用して、UNIX タイムスタンプを渡すことでページが最後に変更された日時を設定できます。クライアントは最終変更日時の値が変更されるまで、キャッシュを引き続き使用します。
lastModified
Flight::route('/news', function () { Flight::lastModified(1234567890); echo 'このコンテンツはキャッシュされます。'; });
ETag キャッシングは Last-Modified と似ていますが、リソースに任意の ID を指定できます:
ETag
Last-Modified
Flight::route('/news', function () { Flight::etag('my-unique-id'); echo 'このコンテンツはキャッシュされます。'; });
lastModified または etag のいずれかを呼び出すと、キャッシュの値が設定されてチェックされます。リクエスト間でキャッシュの値が同じ場合、Flight は直ちに HTTP 304 レスポンスを送信して処理を停止します。
etag
HTTP 304
Flightは、レスポンスヘッダーの一部を生成するのに役立ちますが、ユーザーに送り返す内容の大部分を制御することができます。時々、Responseオブジェクトに直接アクセスできることがありますが、ほとんどの場合はFlightインスタンスを使用してレスポンスを送信します。
Flight
Flightは、出力をバッファリングするためにob_start()を使用しています。これは、echoやprintを使用してユーザーにレスポンスを送信し、Flightがそれをキャプチャして適切なヘッダーとともにユーザーに送り返すことができることを意味します。
echo
print
// これは、「こんにちは、世界!」をユーザーのブラウザに送信します Flight::route('/', function() { echo "こんにちは、世界!"; }); // HTTP/1.1 200 OK // Content-Type: text/html // // こんにちは、世界!
代わりに、write()メソッドを呼び出して本文に追加することもできます。
write()
// これは、「こんにちは、世界!」をユーザーのブラウザに送信します Flight::route('/', function() { // 煩雑ですが、必要な場合には仕事を行います Flight::response()->write("こんにちは、世界!"); // この時点で設定した本文を取得したい場合 // 以下のようにすることができます $body = Flight::response()->getBody(); });
statusメソッドを使用してレスポンスのステータスコードを設定できます。
status
Flight::route('/@id', function($id) { if($id == 123) { Flight::response()->status(200); echo "こんにちは、世界!"; } else { Flight::response()->status(403); echo "禁止されています"; } });
現在のステータスコードを取得したい場合は、引数なしでstatusメソッドを使用できます。
Flight::response()->status(); // 200
writeメソッドを使用してレスポンスボディを設定できますが、echoまたはprintすると、出力バッファリングを介してレスポンスボディとしてキャプチャされます。
write
Flight::route('/', function() { Flight::response()->write("こんにちは、世界!"); }); // 以下と同じ Flight::route('/', function() { echo "こんにちは、世界!"; });
レスポンスボディをクリアしたい場合は、clearBodyメソッドを使用できます。
clearBody
Flight::route('/', function() { if($someCondition) { Flight::response()->write("こんにちは、世界!"); } else { Flight::response()->clearBody(); } });
addResponseBodyCallbackメソッドを使用して、レスポンスボディにコールバックを実行できます。
addResponseBodyCallback
Flight::route('/users', function() { $db = Flight::db(); $users = $db->fetchAll("SELECT * FROM users"); Flight::render('users_table', ['users' => $users]); }); // これにより、どのルートに対してもすべての応答をgzip形式にします Flight::response()->addResponseBodyCallback(function($body) { return gzencode($body, 9); });
複数のコールバックを追加することができ、追加された順に実行されます。これは任意の callable を受け入れるため、クラス配列 [ $class, 'method' ]、クロージャ $strReplace = function($body) { str_replace('hi', 'there', $body); };、または関数名 'minify' を受け入れることができます(たとえば、HTMLコードを縮小化する関数がある場合など)。
[ $class, 'method' ]
$strReplace = function($body) { str_replace('hi', 'there', $body); };
'minify'
注意: flight.v2.output_buffering構成オプションを使用している場合、ルートコールバックは機能しません。
これを特定のルートにのみ適用させたい場合は、ルート自体でコールバックを追加することができます。
Flight::route('/users', function() { $db = Flight::db(); $users = $db->fetchAll("SELECT * FROM users"); Flight::render('users_table', ['users' => $users]); // これにより、このルートへの応答だけがgzip形式になります Flight::response()->addResponseBodyCallback(function($body) { return gzencode($body, 9); }); });
すべてのルートに対してコールバックを適用するためにミドルウェアを使用することもできます。
// MinifyMiddleware.php class MinifyMiddleware { public function before() { // ここでresponse()オブジェクトに対してコールバックを適用します Flight::response()->addResponseBodyCallback(function($body) { return $this->minify($body); }); } protected function minify(string $body): string { // 何らかの方法で本文を縮小化します return $body; } } // index.php Flight::group('/users', function() { Flight::route('', function() { /* ... */ }); Flight::route('/@id', function($id) { /* ... */ }); }, [ new MinifyMiddleware() ]);
headerメソッドを使用して、レスポンスのコンテンツタイプなどのヘッダーを設定できます。
// これは「こんにちは、世界!」をユーザーのブラウザにプレーンテキストとして送信します Flight::route('/', function() { Flight::response()->header('Content-Type', 'text/plain'); // または Flight::response()->setHeader('Content-Type', 'text/plain'); echo "こんにちは、世界!"; });
Flightは、JSONおよびJSONP応答の送信をサポートしています。 JSON応答を送信するには、JSONにエンコードするデータを渡します。
Flight::json(['id' => 123]);
2番目の引数としてステータスコードを渡すこともできます。
Flight::json(['id' => 123], 201);
最後の位置に引数を渡してクリアな印刷を有効にすることもできます。
Flight::json(['id' => 123], 200, true, 'utf-8', JSON_PRETTY_PRINT);
Flight::json()に渡すオプションを変更してより簡単な構文を必要とする場合は、JSONメソッドを再マッピングすることができます。
Flight::json()
Flight::map('json', function($data, $code = 200, $options = 0) { Flight::_json($data, $code, true, 'utf-8', $options); } // これで以下のように使用できます Flight::json(['id' => 123], 200, JSON_PRETTY_PRINT);
JSON応答を送信して実行を停止したい場合は、jsonHaltメソッドを使用できます。 これは、ある種の認証をチェックして、ユーザーが認可されていない場合、即座にJSON応答を送信し、現在の本文内容をクリアして実行を停止する場合に便利です。
jsonHalt
Flight::route('/users', function() { $authorized = someAuthorizationCheck(); // ユーザーが認可されているかどうかをチェック if($authorized === false) { Flight::jsonHalt(['error' => 'Unauthorized'], 401); } // ルートの残りの部分を続行します });
v3.10.0以前では、次のようにする必要がありました:
Flight::route('/users', function() { $authorized = someAuthorizationCheck(); // ユーザーが認可されているかどうかをチェック if($authorized === false) { Flight::halt(401, json_encode(['error' => 'Unauthorized'])); } // ルートの残りの部分を続行します });
JSONPリクエストの場合、コールバック関数を定義するために使用しているクエリパラメータ名をオプションで渡すことができます。
Flight::jsonp(['id' => 123], 'q');
そのため、?q=my_funcを使用してGETリクエストを行うと、出力が次のようになります:
?q=my_func
my_func({"id":123});
クエリパラメータ名を渡さない場合は、デフォルトでjsonpになります。
jsonp
redirect()メソッドを使用して現在のリクエストをリダイレクトできます 新しいURLを渡します。
Flight::redirect('/new/location');
デフォルトでは、FlightはHTTP 303(「他を参照してください」)ステータスコードを送信します。カスタムコードを設定することもできます。
Flight::redirect('/new/location', 401);
haltメソッドを呼び出すことで、いつでもフレームワークを停止できます。
オプションのHTTPステータスコードとメッセージを指定することもできます。
Flight::halt(200, 'ただいまメンテナンス中...');
haltを呼び出すことで、現在までの任意のレスポンス内容が破棄されます。フレームワークを停止して、現在のレスポンスを出力する場合は、stopメソッドを使用します。
clear()メソッドを使用して、レスポンスボディとヘッダーをクリアできます。 これにより、レスポンスに割り当てられた任意のヘッダーがクリアされ、レスポンス本体がクリアされ、ステータスコードが200に設定されます。
clear()
200
Flight::response()->clear();
レスポンスボディだけをクリアしたい場合は、clearBody()メソッドを使用できます。
clearBody()
// これにより、response()オブジェクトに設定された任意のヘッダーが保持されます。 Flight::response()->clearBody();
Flightには、HTTPレベルのキャッシュを簡単に行うための組込みのサポートがあります。 キャッシュ条件が満たされると、FlightはHTTP304 Not Modified応答を返します。 クライアントが同じリソースを再リクエストすると、ローカルにキャッシュされたバージョンを使用するよう促されます。
全体のレスポンスをキャッシュしたい場合は、cache()メソッドを使用し、キャッシュする時間を渡すことができます。
cache()
// これにより、レスポンスが 5 分間キャッシュされます Flight::route('/news', function () { Flight::response()->cache(time() + 300); echo 'このコンテンツはキャッシュされます。'; }); // 代わりに、strtotime()メソッドに渡す文字列を使用することもできます Flight::route('/news', function () { Flight::response()->cache('+5 minutes'); echo 'このコンテンツはキャッシュされます。'; });
lastModifiedメソッドを使用して、ページが最終に変更された日付と時刻を設定できます。 クライアントは、最終変更値が変更されるまでキャッシュを維持します。
ETagキャッシングは、Last-Modifiedと似ていますが、リソースに対して任意のIDを指定できます。
lastModifiedまたはetagを呼び出すと、キャッシュ値が設定およびチェックされます。 リクエスト間でキャッシュ値が同じ場合、Flightは即座にHTTP 304応答を送信して処理を停止します。
ファイルをダウンロードするためのヘルパーメソッドがあります。 downloadメソッドを使用して、パスを渡すことができます。
download
Flight::route('/download', function () { Flight::download('/path/to/file.txt'); });
Flightをグローバルな静的クラスとして実行する代わりに、オブジェクトのインスタンスとして実行することもできます。
require 'flight/autoload.php'; $app = Flight::app(); $app->route('/', function () { echo 'hello world!'; }); $app->start();
静的なメソッドを呼び出す代わりに、同じ名前のインスタンスメソッドをEngineオブジェクトで呼び出すことになります。
redirect メソッドを使用して、新しい URL を指定して現在のリクエストをリダイレクトできます:
redirect
Flight はデフォルトで HTTP 303 ステータスコードを送信します。オプションでカスタムコードを設定できます:
Flightは、デフォルトでいくつかの基本的なテンプレーティング機能を提供します。ビューテンプレートを表示するには、renderメソッドをテンプレートファイルの名前とオプションのテンプレートデータで呼び出します:
render
Flight::render('hello.php', ['name' => 'Bob']);
渡すテンプレートデータは、自動的にテンプレートに注入され、ローカル変数のように参照できます。テンプレートファイルは単純なPHPファイルです。hello.phpテンプレートファイルの内容が次のような場合:
hello.php
Hello, <?= $name ?>!
出力は次のようになります:
Hello, Bob!
また、setメソッドを使用してビュー変数を手動で設定することもできます:
Flight::view()->set('name', 'Bob');
変数nameは今やすべてのビューで利用可能です。したがって、次のように簡単にできます:
name
Flight::render('hello');
renderメソッド内でテンプレートの名前を指定する際に、.php拡張子を省略することができることに注意してください。
.php
デフォルトでは、Flightはテンプレートファイルのために views ディレクトリを参照します。テンプレートの代替パスを設定するためには、次の設定を行います:
views
Flight::set('flight.views.path', '/path/to/views');
ウェブサイトには、入れ替わるコンテンツを持つ単一のレイアウトテンプレートファイルを持つことが一般的です。レイアウトにレンダリングするコンテンツを渡すには、renderメソッドにオプションのパラメータを渡すことができます。
Flight::render('header', ['heading' => 'Hello'], 'headerContent'); Flight::render('body', ['body' => 'World'], 'bodyContent');
その後、ビューには headerContent と bodyContent という名前の保存された変数があります。次に、次のようにしてレイアウトをレンダリングできます:
headerContent
bodyContent
Flight::render('layout', ['title' => 'Home Page']);
テンプレートファイルが次のようになっている場合:
header.php:
header.php
<h1><?= $heading ?></h1>
body.php:
body.php
<div><?= $body ?></div>
layout.php:
layout.php
<html> <head> <title><?= $title ?></title> </head> <body> <?= $headerContent ?> <?= $bodyContent ?> </body> </html>
<html> <head> <title>Home Page</title> </head> <body> <h1>Hello</h1> <div>World</div> </body> </html>
Flightを使用すると、独自のビュークラスを登録するだけでデフォルトのビューエンジンを切り替えることができます。ビューにSmartyテンプレートエンジンを使用する方法は次の通りです:
// Smartyライブラリの読み込み require './Smarty/libs/Smarty.class.php'; // ビュークラスとしてSmartyを登録 // Smartyをロード時に構成するためのコールバック関数も渡す Flight::register('view', Smarty::class, [], function (Smarty $smarty) { $smarty->setTemplateDir('./templates/'); $smarty->setCompileDir('./templates_c/'); $smarty->setConfigDir('./config/'); $smarty->setCacheDir('./cache/'); }); // テンプレートデータを割り当てる Flight::view()->assign('name', 'Bob'); // テンプレートを表示 Flight::view()->display('hello.tpl');
完全性を期すために、Flightのデフォルトのrenderメソッドもオーバーライドする必要があります:
Flight::map('render', function(string $template, array $data): void { Flight::view()->assign($data); Flight::view()->display($template); });
Flight はデフォルトでいくつかの基本的なテンプレート機能を提供します。
より複雑なテンプレートが必要な場合は、カスタムビュー セクションの Smarty と Latte の例を参照してください。
ビューテンプレートを表示するには、テンプレートファイルの名前とオプションのテンプレートデータを使用して render メソッドを呼び出します:
渡すテンプレートデータは自動的にテンプレートに注入され、ローカル変数のように参照できます。テンプレートファイルは単純に PHP ファイルです。hello.php テンプレートファイルの内容が次のような場合:
また、set メソッドを使用してビュー変数を手動で設定することもできます:
変数 name はこれ以降すべてのビューで使用できます。そのため、単に次のように行うことができます:
render メソッドでテンプレートの名前を指定する際に、.php 拡張子を省略することができる点に注意してください。
Flight はデフォルトでテンプレートファイルのための views ディレクトリを探します。テンプレートの代替パスを設定するには、次の構成を設定してください:
ウェブサイトには交換可能なコンテンツを持つ単一のレイアウトテンプレートファイルがあることが一般的です。使用するコンテンツをレイアウトにレンダリングするには、render メソッドにオプションのパラメータを渡すことができます。
その後、headerContent と bodyContent と呼ばれる保存された変数を持つビューがあります。そうすることで、次のようにレイアウトをレンダリングできます:
Flight::render('layout', ['title' => 'ホームページ']);
<html> <head> <title>ホームページ</title> </head> <body> <h1>Hello</h1> <div>World</div> </body> </html>
Flight では、独自のビュークラスを登録することでデフォルトのビューエンジンを簡単に入れ替えることができます。
ビューに Smarty テンプレートエンジンを使用する方法は次のとおりです:
// Smarty ライブラリをロードします require './Smarty/libs/Smarty.class.php'; // ビュークラスとして Smarty を登録します // また、Smarty のロード時に設定するためのコールバック関数を渡します Flight::register('view', Smarty::class, [], function (Smarty $smarty) { $smarty->setTemplateDir('./templates/'); $smarty->setCompileDir('./templates_c/'); $smarty->setConfigDir('./config/'); $smarty->setCacheDir('./cache/'); }); // テンプレートデータを割り当てます Flight::view()->assign('name', 'Bob'); // テンプレートを表示します Flight::view()->display('hello.tpl');
完全性のために、Flight のデフォルトの render メソッドを上書きする必要があります:
ビューに Latte テンプレートエンジンを使用する方法は次のとおりです:
// ビュークラスとして Latte を登録します // また、Latte のロード時に設定するためのコールバック関数を渡します Flight::register('view', Latte\Engine::class, [], function (Latte\Engine $latte) { // ここが Latte がテンプレートをキャッシュする場所です // Latte の素晴らしいところの1つは、テンプレートを変更すると自動的にキャッシュを更新することです! $latte->setTempDirectory(__DIR__ . '/../cache/'); // Latte にとってビューのルートディレクトリがどこにあるかを教えてください。 $latte->setLoader(new \Latte\Loaders\FileLoader(__DIR__ . '/../views/')); }); // ラップして Flight::render() を正しく使用できるようにします Flight::map('render', function(string $template, array $data): void { // これは $latte_engine->render($template, $data); のようなものです echo Flight::view()->render($template, $data); });
Fat-Free(愛称F3)は、迅速に動的かつ堅牢なウェブアプリケーションを構築するのに役立つ強力で使いやすいPHPマイクロフレームワークです。
Flightは多くの点でFat-Freeと比較され、機能とシンプリシティの面ではおそらく最も近しい親戚です。 Fat-FreeにはFlightにはない機能が多く含まれていますが、Flightにはある機能も多くあります。 Fat-Freeは時代遅れになりつつあり、かつてほど人気がありません。
更新頻度が低くなり、コミュニティも以前ほど活発ではありません。コードは十分にシンプルですが、構文の規律が欠如していることが時々読み取りやすさを損なうことがあります。PHP 8.3でも動作しますが、コード自体はまだPHP 5.3であるかのように見えます。
DB \ SQL
active-record
Cache
beforeroute
afterroute
HIVE
Flightは拡張可能なフレームワークとして設計されています。フレームワークにはデフォルトのメソッドやコンポーネントが付属していますが、独自のメソッドをマップしたり、独自のクラスを登録したり、既存のクラスやメソッドをオーバーライドすることができます。
DIC(Dependency Injection Container)をお探しの場合は、Dependency Injection Container ページをご覧ください。
独自のシンプルなカスタムメソッドをマップするには、map 関数を使用します:
// メソッドをマップ Flight::map('hello', function (string $name) { echo "hello $name!"; }); // カスタムメソッドを呼び出す Flight::hello('Bob');
シンプルなカスタムメソッドを作成することは可能ですが、PHPでは標準の関数を作成することを推奨します。これにはIDEでの自動補完があり、読みやすくなります。 上記のコードの相当するものは次の通りです:
function hello(string $name) { echo "hello $name!"; } hello('Bob');
これは、メソッドに変数を渡して予想される値を取得する必要がある場合により使用されます。以下のように register() メソッドを使用すると、構成を渡してから事前に構成されたクラスを呼び出すためにより使用されます。
register()
独自のクラスを登録して構成するには、register 関数を使用します:
// クラスを登録 Flight::register('user', User::class); // クラスのインスタンスを取得する $user = Flight::user();
register メソッドでは、クラスのコンストラクタにパラメータを渡すこともできます。 したがって、カスタムクラスをロードするとき、事前に初期化された状態で取得されます。 追加の配列を渡すことでコンストラクタパラメータを定義することができます。 以下はデータベース接続をロードする例です:
// コンストラクタパラメータを持つクラスを登録 Flight::register('db', PDO::class, ['mysql:host=localhost;dbname=test', 'user', 'pass']); // クラスのインスタンスを取得する // これにより、指定されたパラメータでオブジェクトが作成されます // // new PDO('mysql:host=localhost;dbname=test','user','pass'); // $db = Flight::db(); // 後でコード内で必要になった場合は、同じメソッドを再度呼び出すだけです class SomeController { public function __construct() { $this->db = Flight::db(); } }
追加のコールバックパラメータを渡すと、クラスの構築直後に即座に実行されます。 これにより、新しいオブジェクトのセットアップ手順を実行できます。 コールバック関数は、新しいオブジェクトのインスタンスを表すパラメータを1つ受け取ります。
// 構築されたオブジェクトがコールバックに渡されます Flight::register( 'db', PDO::class, ['mysql:host=localhost;dbname=test', 'user', 'pass'], function (PDO $db) { $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } );
デフォルトでは、クラスをロードするたびに共有インスタンスが取得されます。 クラスの新しいインスタンスを取得するには、単にパラメータとして false を渡します:
// クラスの共有インスタンス $shared = Flight::db(); // クラスの新しいインスタンス $new = Flight::db(false);
マップされたメソッドはクラスの登録よりも優先されます。同じ名前で両方を宣言する場合、マップされたメソッドのみが呼び出されます。
Flightを使用すると、コードを変更せずに独自のニーズに合わせてデフォルトの機能をオーバーライドすることができます。 オーバーライドできるすべてのメソッドを確認するには、こちら をご覧ください。
たとえば、FlightがURLをルートに一致させられない場合、notFound メソッドが呼び出され、一般的な HTTP 404 応答が送信されます。この動作をオーバーライドするには、map メソッドを使用します:
Flightは、フレームワークのコアコンポーネントを置換することもできます。 たとえば、デフォルトのルータークラスを独自のカスタムクラスで置き換えることができます:
ただし、map や register のようなフレームワークメソッドはオーバーライドできません。これをしようとするとエラーが発生します。
FlightはJSONとJSONPレスポンスを送信するためのサポートを提供します。 JSONレスポンスを送信するには、JSONエンコードするデータを渡します:
JSONPリクエストの場合は、コールバック関数を定義するために使用するクエリパラメータ名をオプションで指定できます:
そのため、?q=my_funcを使用してGETリクエストを行うと、次の出力が返されるはずです:
クエリパラメータ名を指定しない場合、デフォルトでjsonpになります。
Slim は、シンプルでありながらパワフルなウェブアプリケーションやAPIを素早く作成できるPHPマイクロフレームワークです。
v3の一部機能に対するインスピレーションの多くは、実際にはSlimからきています。ルートのグループ化や、ミドルウェアの特定の順序での実行といった2つの機能はSlimからの影響を受けています。Slim v3はシンプルさを重視した形でリリースされましたが、v4に関しては賛否両論があります。
オートローディングは、PHPにおいてクラスを読み込むディレクトリを指定する概念です。これは、requireやincludeを使用してクラスをロードするよりも有益です。Composerパッケージを使用する際にも必要です。
require
include
デフォルトでは、FlightクラスはComposerのおかげで自動的にオートロードされます。ただし、独自のクラスをオートロードする場合は、Flight::path()メソッドを使用してクラスを読み込むディレクトリを指定できます。
Flight::path()
以下のようなディレクトリツリーを持つとします:
# 例えばのパス /home/user/project/my-flight-project/ ├── app │ ├── cache │ ├── config │ ├── controllers - このプロジェクトのコントローラーが含まれる │ ├── translations │ ├── UTILS - このアプリケーション専用のクラスが含まれる(これは後の例のためにわざと全てキャピタライズされています) │ └── views └── public └── css └── js └── index.php
このドキュメンテーションサイトと同じファイル構造であることに気づかれたかもしれません。
次のように各ディレクトリを指定できます:
/** * public/index.php */ // オートローダーにパスを追加 Flight::path(__DIR__.'/../app/controllers/'); Flight::path(__DIR__.'/../app/utils/'); /** * app/controllers/MyController.php */ // 名前空間は必要ありません // すべてのオートロードされるクラスはパスカルケース(各単語を大文字にして、スペースなし)であることが推奨されます // ローダー::setV2ClassLoading(false);を実行することで、クラス名にパスカル_スネーク_ケースを使用できます(バージョン3.7.2以降) class MyController { public function index() { // 何かを実行 } }
名前空間がある場合、これを実装するのは実際には非常に簡単です。Flight::path()メソッドを使用して、アプリケーションのルートディレクトリ(ドキュメントルートや public/ フォルダではない)を指定する必要があります。
public/
/** * public/index.php */ // オートローダーにパスを追加 Flight::path(__DIR__.'/../');
これがあなたのコントローラーの見た目です。以下の例を見てくださいが、重要な情報はコメントに注目してください。
/** * app/controllers/MyController.php */ // 名前空間は必須です // 名前空間はディレクトリ構造と同じです // 名前空間はディレクトリ構造と同じケースを使用する必要があります // 名前空間とディレクトリにはアンダースコアを含めることはできません(Loader::setV2ClassLoading(false)が設定されていない限り) namespace app\controllers; // すべてのオートロードされるクラスはパスカルケース(各単語を大文字にして、スペースなし)であることが推奨されます // ローダー::setV2ClassLoading(false);を実行することで、クラス名にパスカル_スネーク_ケースを使用できます(バージョン3.7.2以降) class MyController { public function index() { // 何かを実行 } }
それと、utilsディレクトリ内のクラスをオートロードしたい場合は、基本的に同じことを行います:
/** * app/UTILS/ArrayHelperUtil.php */ // 名前空間はディレクトリ構造とケースと一致する必要があります(UTILSディレクトリがファイルツリー内で全てキャピタライズされていることに注意) namespace app\UTILS; class ArrayHelperUtil { public function changeArrayCase(array $array) { // 何かを実行 } }
バージョン3.7.2以降、Loader::setV2ClassLoading(false);を実行することで、クラス名にパスカル_スネーク_ケースを使用できます。これにより、クラス名にアンダースコアを使用できます。これは推奨されませんが、必要な方には利用可能です。
Loader::setV2ClassLoading(false);
/** * public/index.php */ // オートローダーにパスを追加 Flight::path(__DIR__.'/../app/controllers/'); Flight::path(__DIR__.'/../app/utils/'); Loader::setV2ClassLoading(false); /** * app/controllers/My_Controller.php */ // 名前空間は必要ありません class My_Controller { public function index() { // 何かを実行 } }
このページでは、Flightを使用している際に遭遇するかもしれない一般的な問題のトラブルシューティングを支援します。
404 Not Found エラーが表示される場合(しかし、それが実際に存在していることを誓って、タイプミスではないと主張する場合)、実際にはこれは、単にそれをエコーするのではなく、ルートエンドポイントで値を返すことが問題である可能性があります。これは意図的に行われている理由ですが、開発者の一部には忍び込む可能性があります。
Flight::route('/hello', function(){ // これが 404 Not Found エラーの原因となる可能性があります return 'Hello World'; }); // おそらく望む動作 Flight::route('/hello', function(){ echo 'Hello World'; });
これは、ルーターに組み込まれている特別なメカニズムのために行われます。このメカニズムは、戻り出力を単一の「次のルートに移動する」として処理します。この動作はRoutingセクションで文書化されています。
これにはいくつかの理由が考えられます。以下にいくつかの例を示しますが、autoloadingセクションも確認してください。
最も一般的なのは、クラス名がファイル名と一致していないことです。
クラス名が MyClass の場合、ファイル名は MyClass.php とする必要があります。クラス名が MyClass でファイル名が myclass.php の場合、オートローダーはそれを見つけることができません。
MyClass
MyClass.php
myclass.php
名前空間を使用している場合、名前空間はディレクトリ構造と一致している必要があります。
// コード // もし MyController が app/controllers ディレクトリにあり、名前空間が付いている場合 // この方法は機能しません。 Flight::route('/hello', 'MyController->hello'); // 以下のオプションのいずれかを選択する必要があります Flight::route('/hello', 'app\controllers\MyController->hello'); // または先頭に use 文がある場合 use app\controllers\MyController; Flight::route('/hello', [ MyController::class, 'hello' ]); // また、以下のように記述することもできます Flight::route('/hello', MyController::class.'->hello'); // また... Flight::route('/hello', [ 'app\controllers\MyController', 'hello' ]);
path()
スケルトンアプリでは、これは config.php ファイル内で定義されていますが、クラスを見つけるためには、使用する前に path() メソッドが定義されていることを確認する必要があります(おそらくディレクトリのルートに)。
config.php
// オートローダーにパスを追加 Flight::path(__DIR__.'/../');
もしComposerを使用している場合、次のコマンドを実行できます:
composer require flightphp/core
または、ファイルをダウンロードして、それらをウェブディレクトリに直接展開することもできます。
Apacheを使用する場合、.htaccessファイルを以下のように編集してください:
.htaccess
RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php [QSA,L]
注意: サブディレクトリでflightを使用する必要がある場合は、RewriteEngine Onの直後に行を追加してください: RewriteBase /subdir/。 注意: データベースや環境ファイルなどのすべてのサーバファイルを保護する必要がある場合は、.htaccessファイルに以下を追加してください:
注意: サブディレクトリでflightを使用する必要がある場合は、RewriteEngine Onの直後に行を追加してください: RewriteBase /subdir/。
RewriteEngine On
RewriteBase /subdir/
注意: データベースや環境ファイルなどのすべてのサーバファイルを保護する必要がある場合は、.htaccessファイルに以下を追加してください:
RewriteEngine On RewriteRule ^(.*)$ index.php
Nginxを使用する場合、以下をサーバ定義に追加してください:
server { location / { try_files $uri $uri/ /index.php; } }
<?php // Composerを使用している場合、オートローダーを要求します。 require 'vendor/autoload.php'; // Composerを使用していない場合、フレームワークを直接ロードします // require 'flight/Flight.php'; // 次に、ルートを定義し、リクエストを処理するための関数を割り当てます。 Flight::route('/', function () { echo 'hello world!'; }); // 最後に、フレームワークをスタートします。 Flight::start();
Copyright © 2024 @mikecao, @n0nag0n
2024
@mikecao, @n0nag0n
個人が複製の許可を得ることができるように、このソフトウェアおよび関連ドキュメントファイル(以下「ソフトウェア」という)のコピーを入手することができます。 ソフトウェアを使用、コピー、変更、マージ、公開、配布、サブライセンス、販売する権利などを含む、制限なしでソフトウェアを扱う権利が、以下の条件に従って人々にそれを許可します:
上記の著作権表示およびこの許諾表示は、ソフトウェアのすべての複製または実質的な部分に含まれている必要があります。
ソフトウェアは、「現状有姿」で提供され、商品性、特定目的への適合性、および権利侵害を含むがこれに限定されない、いかなる種類の保証もなしに提供されます。 著作者または著作権保持者は、ソフトウェアまたは使用または他の取引に起因する契約上の行為、不法行為、その他の行為から生じるクレーム、損害、その他の責任について一切責任を負いません。
フライトは、PHP向けの高速でシンプルで拡張性のあるフレームワークです。非常に汎用性が高く、あらゆる種類のWebアプリケーション構築に使用できます。単純さを念頭に置いて構築され、理解しやすく使いやすい方法で記述されています。
フライトは、PHPに新しい人やWebアプリケーション構築の方法を学びたい人にとって素晴らしい初心者向けフレームワークです。また、Webアプリケーションに対してより多くの制御を望む経験豊富な開発者にとっても優れたフレームワークです。RESTful API、シンプルなWebアプリケーション、または複雑なWebアプリケーションを簡単に構築できるように設計されています。
<?php // if installed with composer require 'vendor/autoload.php'; // or if installed manually by zip file // require 'flight/Flight.php'; Flight::route('/', function() { echo 'hello world!'; }); Flight::route('/json', function() { Flight::json(['hello' => 'world']); }); Flight::start();
簡単ですね?ドキュメントでフライトについて詳しく学ぶ!
フライトフレームワークを使って始めるのに役立つ例のアプリケーションがあります。flightphp/skeleton に移動して開始方法に関する指示を参照してください!また、examples ページを訪れると、フライトで行えるいくつかのアイデアを参考にできます。
Matrix Chatでの参加をお待ちしています。#flight-php-framework:matrix.org でチャットしましょう。
フライトに貢献する方法は2つあります:
フライトはPHP 7.4以上が必要です。
注意: PHP 7.4がサポートされている理由は、執筆時点(2024年)で一部のLTS Linuxディストリビューションでデフォルトバージョンとして採用されているためです。PHP >8への移行を強制すると、これらのユーザーに多くの問題が生じる可能性があります。また、このフレームワークはPHP >8もサポートしています。
フライトはMIT ライセンスの下でリリースされています。
overclokk/cookie はアプリ内でクッキーを管理するためのシンプルなライブラリです。
composerを使用して簡単にインストールできます。
composer require overclokk/cookie
使用法は、Flightクラスに新しいメソッドを登録するだけです。
use Overclokk\Cookie\Cookie; /* * ブートストラップまたはpublic/index.phpファイルに設定 */ Flight::register('cookie', Cookie::class); /** * ExampleController.php */ class ExampleController { public function login() { // クッキーを設定します // インスタンスを取得するためfalseである必要があります // オートコンプリートを有効にしたい場合は以下のコメントを使用してください /** @var \Overclokk\Cookie\Cookie $cookie */ $cookie = Flight::cookie(false); $cookie->set( 'stay_logged_in', // クッキーの名前 '1', // 設定したい値 86400, // クッキーの有効期間(秒) '/', // クッキーが利用可能なパス 'example.com', // クッキーが利用可能なドメイン true, // セキュアな HTTPS 接続でのみクッキーが送信されます true // クッキーはHTTPプロトコルを介してのみ利用可能です ); // オプションで、デフォルト値を維持したい場合や、 // 長期間にわたってクッキーを簡単に設定したい場合 $cookie->forever('stay_logged_in', '1'); } public function home() { // クッキーがあるかどうかをチェック if (Flight::cookie()->has('stay_logged_in')) { // 例えば、ダッシュボードエリアにリダイレクトします。 Flight::redirect('/dashboard'); } } }
defuse/php-encryption はデータの暗号化と復号を行うために使用できるライブラリです。すぐにデータの暗号化と復号を始めることはかなり簡単です。ライブラリの使用方法や暗号化に関連する重要なセキュリティの問題を説明する素晴らしいtutorialがあります。
composerを使用して簡単にインストールします。
composer require defuse/php-encryption
その後、暗号化キーを生成する必要があります。
vendor/bin/generate-defuse-key
これにより、安全に保持する必要があるキーが生成されます。キーは、ファイルの末尾にある配列内のapp/config/config.phpファイルに保存できます。完璧な場所ではありませんが、少なくとも何かです。
app/config/config.php
ライブラリと暗号化キーがあるので、データの暗号化と復号を開始できます。
use Defuse\Crypto\Crypto; use Defuse\Crypto\Key; /* * ブートストラップまたはpublic/index.phpファイルに設定します */ // 暗号化メソッド Flight::map('encrypt', function($raw_data) { $encryption_key = /* $config['encryption_key']またはキーを配置した場所のfile_get_contents */; return Crypto::encrypt($raw_data, Key::loadFromAsciiSafeString($encryption_key)); }); // 復号メソッド Flight::map('decrypt', function($encrypted_data) { $encryption_key = /* $config['encryption_key']またはキーを配置した場所のfile_get_contents */; try { $raw_data = Crypto::decrypt($encrypted_data, Key::loadFromAsciiSafeString($encryption_key)); } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) { // 攻撃! 間違ったキーが読み込まれたか、暗号文が作成されてから変更された可能性があります -- データベースで破損されたか、攻撃を実行しようとするEveによって意図的に変更された可能性があります。 // ... アプリケーションに適した方法でこのケースを処理します ... } return $raw_data; }); Flight::route('/encrypt', function() { $encrypted_data = Flight::encrypt('これは秘密です'); echo $encrypted_data; }); Flight::route('/decrypt', function() { $encrypted_data = '...'; // どこかから暗号化されたデータを取得します $decrypted_data = Flight::decrypt($encrypted_data); echo $decrypted_data; });
軽量でシンプルかつスタンドアロンのPHPインファイルキャッシングクラス
利点
コードを表示するにはここをクリックしてください。
Composerを介してインストールする:
composer require wruczek/php-file-cache
使用法は非常に簡単です。
use Wruczek\PhpFileCache\PhpFileCache; $app = Flight::app(); // キャッシュが保存されるディレクトリをコンストラクタに渡します $app->register('cache', PhpFileCache::class, [ __DIR__ . '/../cache/' ], function(PhpFileCache $cache) { // これにより、キャッシュは本番モードでのみ使用されることが保証されます // ENVIRONMENTは、ブートストラップファイルやアプリ内の他の場所で設定されている定数です $cache->setDevMode(ENVIRONMENT === 'development'); });
その後、次のようにコードで使用できます:
// キャッシュインスタンス取得 $cache = Flight::cache(); $data = $cache->refreshIfExpired('simple-cache-test', function () { return date("H:i:s"); // キャッシュするデータを返します }, 10); // 10秒 // または $data = $cache->retrieve('simple-cache-test'); if(empty($data)) { $data = date("H:i:s"); $cache->store('simple-cache-test', $data, 10); // 10秒 }
完全なドキュメントを確認するにはhttps://github.com/Wruczek/PHP-File-Cacheを訪れ、examplesフォルダをご覧ください。
これは、アプリケーション内に複数のロールがあり、各ロールに少しずつ異なる機能がある場合にプロジェクトで使用できる権限モジュールです。このモジュールは、各ロールに対して権限を定義し、その後現在のユーザーが特定のページにアクセスする権限があるか、または特定のアクションを実行する権限があるかを確認できます。
こちらをクリックしてGitHubのリポジトリを確認してください。
composer require flightphp/permissions を実行して、準備完了です!
composer require flightphp/permissions
まず、権限を設定し、その後アプリケーションに権限がどういう意味なのかを伝える必要があります。最終的には、$Permissions->has()、->can()、またはis() で権限を確認します。has() と can() には同じ機能があるため、コードをより読みやすくするために名前が異なります。
$Permissions->has()
->can()
is()
has()
can()
アプリケーションに、ユーザーがログインしているかどうかをチェックする機能があると仮定してください。次のように権限オブジェクトを作成できます:
// index.php require 'vendor/autoload.php'; // 一部のコード // おそらく誰が現在の役割であるかを示すものがあるでしょう // 多分現在の役割を定義するセッション変数から現在の役割を取得する何かがあるでしょう、 // これはログイン後に、そうでない場合は「guest」または「public」のロールを持っています。 $current_role = 'admin'; // 権限の設定 $permission = new \flight\Permission($current_role); $permission->defineRule('loggedIn', function($current_role) { return $current_role !== 'guest'; }); // おそらくこのオブジェクトを Flight にある場所に持たせたいと思うでしょう Flight::set('permission', $permission);
次に、どこかのコントローラーには、次のようなものがあるかもしれません。
<?php // 一部のコントローラー class SomeController { public function someAction() { $permission = Flight::get('permission'); if ($permission->has('loggedIn')) { // 何かを実行 } else { // 他の処理を実行 } } }
また、この機能を使用して、アプリケーション内で何かを行う権限があるかどうかを追跡することもできます。 たとえば、ソフトウェア上で投稿とやり取りできる方法がある場合、特定のアクションを実行できる権限を持っているかどうかを確認できます。
$current_role = 'admin'; // 権限の設定 $permission = new \flight\Permission($current_role); $permission->defineRule('post', function($current_role) { if($current_role === 'admin') { $permissions = ['create', 'read', 'update', 'delete']; } else if($current_role === 'editor') { $permissions = ['create', 'read', 'update']; } else if($current_role === 'author') { $permissions = ['create', 'read']; } else if($current_role === 'contributor') { $permissions = ['create']; } else { $permissions = []; } return $permissions; }); Flight::set('permission', $permission);
次に、どこかのコントローラーには...
class PostController { public function create() { $permission = Flight::get('permission'); if ($permission->can('post.create')) { // 何かを実行 } else { // 他の処理を実行 } } }
権限を定義するクロージャに依存関係を注入することができます。これは、チェックするデータポイントとしてトグル、ID、その他のデータポイントを持っている場合に便利です。同じことが Class->Method 型の呼び出しでも機能しますが、引数はメソッド内で定義します。
$Permission->defineRule('order', function(string $current_role, MyDependency $MyDependency = null) { // ... コード }); // コントローラーファイル内 public function createOrder() { $MyDependency = Flight::myDependency(); $permission = Flight::get('permission'); if ($permission->can('order.create', $MyDependency)) { // 何かを実行 } else { // 他の処理を実行 } }
namespace MyApp; class Permissions { public function order(string $current_role, MyDependency $MyDependency = null) { // ... コード } }
クラスを使用して権限を定義することもできます。コードをきれいに保ちたい場合に便利です。次のように行うことができます:
<?php // ブートストラップコード $Permissions = new \flight\Permission($current_role); $Permissions->defineRule('order', 'MyApp\Permissions->order'); // myapp/Permissions.php namespace MyApp; class Permissions { public function order(string $current_role, int $user_id) { // 事前に設定したと仮定します /** @var \flight\database\PdoWrapper $db */ $db = Flight::db(); $allowed_permissions = [ 'read' ]; // 誰でも注文を表示できます if($current_role === 'manager') { $allowed_permissions[] = 'create'; // マネージャーは注文を作成できます } $some_special_toggle_from_db = $db->fetchField('SELECT some_special_toggle FROM settings WHERE id = ?', [ $user_id ]); if($some_special_toggle_from_db) { $allowed_permissions[] = 'update'; // ユーザーが特別なトグルを持っている場合、注文を更新できます } if($current_role === 'admin') { $allowed_permissions[] = 'delete'; // 管理者は注文を削除できます } return $allowed_permissions; } }
クールな部分は、メソッドのすべての権限を自動的にマップするショートカットもあることです(これもキャッシュされる可能性があります!!!)。したがって、order() と company() というメソッドがある場合、$Permissions->has('order.read') や $Permissions->has('company.read') を実行することができます。これらを定義することは非常に難しいので、ここで一緒にとどまります。これを行うには、次の手順を行う必要があります:
order()
company()
$Permissions->has('order.read')
$Permissions->has('company.read')
グループ化したい権限クラスを作成します。
class MyPermissions { public function order(string $current_role, int $order_id = 0): array { // 権限を決定するためのコード return $permissions_array; } public function company(string $current_role, int $company_id): array { // 権限を決定するためのコード return $permissions_array; } }
次に、このライブラリを使用して権限を検出できるようにします。
$Permissions = new \flight\Permission($current_role); $Permissions->defineRulesFromClassMethods(MyApp\Permissions::class); Flight::set('permissions', $Permissions);
最後に、コードベースで権限を呼び出して、ユーザーが与えられた権限を実行できるかどうかを確認します。
class SomeController { public function createOrder() { if(Flight::get('permissions')->can('order.create') === false) { die('You can\'t create an order. Sorry!'); } } }
キャッシュを有効にするには、単純なwruczak/phpfilecacheライブラリを参照してください。これを有効にする例は以下の通りです。
// この $app はあなたのコードの一部である可能性があり、 // コンストラクター内で Flight::app() から取得されるか // null を渡すと、それがコンストラクター内で取得されます $app = Flight::app(); // 現時点では、ファイルキャッシュとしてこれを受け入れます。今後他のものも簡単に追加できます。 $Cache = new Wruczek\PhpFileCache\PhpFileCache; $Permissions = new \flight\Permission($current_role, $app, $Cache); $Permissions->defineRulesFromClassMethods(MyApp\Permissions::class, 3600); // キャッシュする秒数。キャッシュを使用しない場合はこれをオフにしてください
Flightは非常に拡張可能です。Flightアプリケーションに機能を追加するために使用できるプラグインがいくつかあります。いくつかはFlightチームによって公式にサポートされており、他には開始を手助けするためのミクロ/ライトライブラリがあります。
キャッシュはアプリケーションの高速化に役立つ方法です。Flightと使用できるキャッシュライブラリがいくつかあります。
開発を行うローカル環境ではデバッグが重要です。いくつかのプラグインを使用するとデバッグ体験を向上させることができます。
データベースはほとんどのアプリケーションの中心です。これによりデータの保存と取得が可能になります。一部のデータベースライブラリはクエリの記述や実行を簡素化するラッパーであり、一部は完全なORMです。
APIにはあまり役立たないが、Webアプリケーションの構築にはセッションが状態とログイン情報の維持に重要です。
テンプレートはUIを持つWebアプリケーションにとって重要です。Flightと使用できるいくつかのテンプレートエンジンがあります。
共有したいプラグインがありますか?リストに追加するためにプルリクエストを送信してください!
Flight には PDO 用のヘルパークラスが付属しています。これにより、準備/実行/fetchAll() の混乱を簡単にクエリすることができます。データベースのクエリが大幅に簡素化されます。各行の結果は Flight Collection クラスとして返され、配列構文またはオブジェクト構文を使用してデータにアクセスできます。
// PDO ヘルパークラスを登録します Flight::register('db', \flight\database\PdoWrapper::class, ['mysql:host=localhost;dbname=cool_db_name', 'user', 'pass', [ PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'utf8mb4\'', PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_STRINGIFY_FETCHES => false, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ] ]);
このオブジェクトは PDO を拡張しているため、通常の PDO メソッドをすべて使用できます。データベースのクエリをより簡単にするために次のメソッドが追加されています:
runQuery(string $sql, array $params = []): PDOStatement
INSERT や UPDATE に使用したり、SELECT を while ループで使用する予定がある場合に使用します。
$db = Flight::db(); $statement = $db->runQuery("SELECT * FROM table WHERE something = ?", [ $something ]); while($row = $statement->fetch()) { // ... } // またはデータベースに書き込む場合 $db->runQuery("INSERT INTO table (name) VALUES (?)", [ $name ]); $db->runQuery("UPDATE table SET name = ? WHERE id = ?", [ $name, $id ]);
fetchField(string $sql, array $params = []): mixed
クエリから最初のフィールドを取得します
$db = Flight::db(); $count = $db->fetchField("SELECT COUNT(*) FROM table WHERE something = ?", [ $something ]);
fetchRow(string $sql, array $params = []): array
クエリから1行を取得します
$db = Flight::db(); $row = $db->fetchRow("SELECT id, name FROM table WHERE id = ?", [ $id ]); echo $row['name']; // または echo $row->name;
fetchAll(string $sql, array $params = []): array
クエリからすべての行を取得します
$db = Flight::db(); $rows = $db->fetchAll("SELECT id, name FROM table WHERE something = ?", [ $something ]); foreach($rows as $row) { echo $row['name']; // または echo $row->name; }
IN()
IN() ステートメント用の便利なラッパーもあります。IN() のプレースホルダーとして単一のクエスチョンマークを渡し、その後に値の配列を単純に渡すことができます。以下はその例です:
$db = Flight::db(); $name = 'Bob'; $company_ids = [1,2,3,4,5]; $rows = $db->fetchAll("SELECT id, name FROM table WHERE name = ? AND company_id IN (?)", [ $name, $company_ids ]);
// 例として、このラッパーを使用する方法とルートを示します Flight::route('/users', function () { // すべてのユーザーを取得 $users = Flight::db()->fetchAll('SELECT * FROM users'); // すべてのユーザーを表示 $statement = Flight::db()->runQuery('SELECT * FROM users'); while ($user = $statement->fetch()) { echo $user['name']; // または echo $user->name; } // 単一のユーザーを取得 $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); // 単一の値を取得 $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); // 進行補助として IN() 構文を使用します (IN が大文字であることを確認してください) $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]); // またはこのようにもできます $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [ '1,2,3,4,5']); // 新しいユーザーを挿入します Flight::db()->runQuery("INSERT INTO users (name, email) VALUES (?, ?)", ['Bob', 'bob@example.com']); $insert_id = Flight::db()->lastInsertId(); // ユーザーを更新します Flight::db()->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 123]); // ユーザーを削除します Flight::db()->runQuery("DELETE FROM users WHERE id = ?", [123]); // 影響を受けた行数を取得します $statement = Flight::db()->runQuery("UPDATE users SET name = ? WHERE name = ?", ['Bob', 'Sally']); $affected_rows = $statement->rowCount(); });
PHPセッションマネージャー(非同期、フラッシュ、セグメント、セッション暗号化)。セッションデータのオプションの暗号化/復号にPHP open_sslを使用します。ファイル、MySQL、Redis、およびMemcachedをサポートしています。
こちらをクリックしてコードを表示してください。
Composerを使用してインストールしてください。
composer require ghostff/session
デフォルトの設定を使用するには何も渡す必要はありません。詳細な設定については、Github Readmeを参照してください。
use Ghostff\Session\Session; require 'vendor/autoload.php'; $app = Flight::app(); $app->register('session', Session::class); // 1つ覚えておくべきことは、各ページの読み込みごとにセッションをコミットする必要があることです // または構成でauto_commitを実行する必要があります。
以下は、この方法を使用する例です。
Flight::route('POST /login', function() { $session = Flight::session(); // ここにログインロジックなどを記述します // パスワードの検証などを行います // ログインに成功した場合 $session->set('is_logged_in', true); $session->set('user', $user); // セッションに書き込むたびに、明示的にコミットする必要があります。 $session->commit(); }); // このチェックは制限されたページのロジック内にあるか、ミドルウェアでラップされています。 Flight::route('/some-restricted-page', function() { $session = Flight::session(); if(!$session->get('is_logged_in')) { Flight::redirect('/login'); } // ここに制限されたページのロジックを記述します }); // ミドルウェアバージョン Flight::route('/some-restricted-page', function() { // 通常のページロジック })->addMiddleware(function() { $session = Flight::session(); if(!$session->get('is_logged_in')) { Flight::redirect('/login'); } });
以下は、この方法を使用するより複雑な例です。
use Ghostff\Session\Session; require 'vendor/autoload.php'; $app = Flight::app(); // カスタムパスをセッション構成ファイルに設定し、セッションIDにランダムな文字列を指定します $app->register('session', Session::class, [ 'path/to/session_config.php', bin2hex(random_bytes(32)) ], function(Session $session) { // または手動で構成オプションをオーバーライドできます $session->updateConfiguration([ // セッションデータをデータベースに格納する場合(「すべてのデバイスからログアウト」のような機能が必要な場合に適しています) Session::CONFIG_DRIVER => Ghostff\Session\Drivers\MySql::class, Session::CONFIG_ENCRYPT_DATA => true, Session::CONFIG_SALT_KEY => hash('sha256', 'my-super-S3CR3T-salt'), // これを他のものに変更してください Session::CONFIG_AUTO_COMMIT => true, // 必要に応じておよび/またはセッションのコミットが難しい場合にのみ行います。 // さらにFlight::after('start', function() { Flight::session()->commit(); });を実行できます。 Session::CONFIG_MYSQL_DS => [ 'driver' => 'mysql', # PDO dns用のデータベースドライバー 例(mysql:host=...;dbname=...) 'host' => '127.0.0.1', # データベースホスト 'db_name' => 'my_app_database', # データベース名 'db_table' => 'sessions', # データベースのテーブル 'db_user' => 'root', # データベースのユーザー名 'db_pass' => '', # データベースのパスワード 'persistent_conn'=> false, # スクリプトがデータベースに話すたびに新しい接続を確立するオーバーヘッドを避けるため、ウェブアプリケーションが高速になります。バックサイドを見つけてください ] ]); } );
セッションデータを設定しており、リクエスト間で保持されていない場合は、セッションデータをコミットするのを忘れている可能性があります。これは、セッションデータを設定した後に$session->commit()を呼び出すことで行えます。
$session->commit()
Flight::route('POST /login', function() { $session = Flight::session(); // ここにログインロジックなどを記述します // パスワードの検証などを行います // ログインに成功した場合 $session->set('is_logged_in', true); $session->set('user', $user); // セッションに書き込むたびに、明示的にコミットする必要があります。 $session->commit(); });
別の方法は、セッションサービスを設定する際に、構成でauto_commitをtrueに設定することです。これにより、各リクエスト後に自動的にセッションデータがコミットされます。
auto_commit
$app->register('session', Session::class, [ 'path/to/session_config.php', bin2hex(random_bytes(32)) ], function(Session $session) { $session->updateConfiguration([ Session::CONFIG_AUTO_COMMIT => true, ]); } );
さらに、Flight::after('start', function() { Flight::session()->commit(); });を使用して、各リクエスト後にセッションデータをコミットできます。
Flight::after('start', function() { Flight::session()->commit(); });
詳細なドキュメントについては、Github Readmeをご覧ください。構成オプションは、default_config.phpファイル自体で詳細に説明されています。パッケージ自体を調査したい場合は、コードが理解しやすいです。
ランウェイはCLIアプリケーションで、Flightアプリケーションの管理を支援します。コントローラを生成したり、すべてのルートを表示したりすることができます。優れたadhocore/php-cliライブラリに基づいています。
こちらをクリックして、コードを表示してください。
composer require flightphp/runway
ランウェイを実行する最初の回は、セットアッププロセスを進め、プロジェクトのルートに.runway.json構成ファイルを作成します。このファイルには、ランウェイが正しく動作するために必要ないくつかの構成が含まれています。
.runway.json
ランウェイには、Flightアプリケーションを管理するために使用できる複数のコマンドがあります。ランウェイを使用する方法は2つあります。
php runway [command]
vendor/bin/runway [command]
任意のコマンドに対して、--helpフラグを渡すと、そのコマンドの使用方法に関するより詳細な情報を取得できます。
--help
php runway routes --help
以下はいくつかの例です。
.runway.jsonファイルの構成に基づいて、デフォルトの場所は app/controllers/ ディレクトリにコントローラを生成します。
app/controllers/
php runway make:controller MyController
.runway.jsonファイルの構成に基づいて、デフォルトの場所は app/records/ ディレクトリにコントローラを生成します。
app/records/
php runway make:record users
たとえば、次のスキーマを持つ users テーブルがある場合:id、name、email、created_at、updated_at、app/records/UserRecord.php ファイルに類似したファイルが作成されます:
users
email
created_at
updated_at
app/records/UserRecord.php
<?php declare(strict_types=1); namespace app\records; /** * ユーザーテーブルのアクティブレコードクラス。 * @link https://docs.flightphp.com/awesome-plugins/active-record * * @property int $id * @property string $name * @property string $email * @property string $created_at * @property string $updated_at * // 関係を定義した場合、ここに関係を追加できます * @property CompanyRecord $company 関係の例 */ class UserRecord extends \flight\ActiveRecord { /** * @var array $relations モデルの関係を設定します * https://docs.flightphp.com/awesome-plugins/active-record#relationships */ protected array $relations = []; /** * コンストラクタ * @param mixed $databaseConnection データベースへの接続 */ public function __construct($databaseConnection) { parent::__construct($databaseConnection, 'users'); } }
登録されているすべてのFlightのルートを表示します。
php runway routes
特定のルートのみを表示したい場合、フラグを渡してルートをフィルタリングできます。
# GETルートのみを表示 php runway routes --get # POSTルートのみを表示 php runway routes --post # など
Flight向けのパッケージを作成しているか、プロジェクトに独自のカスタムコマンドを追加したい場合は、プロジェクト/パッケージ向けに src/commands/、flight/commands/、app/commands/、または commands/ ディレクトリを作成してください。
src/commands/
flight/commands/
app/commands/
commands/
コマンドを作成するには、AbstractBaseCommandクラスを拡張し、__constructメソッドとexecuteメソッドを最低限実装します。
AbstractBaseCommand
__construct
execute
<?php declare(strict_types=1); namespace flight\commands; class ExampleCommand extends AbstractBaseCommand { /** * コンストラクタ * * @param array<string,mixed> $config .runway-config.jsonからのJSON構成 */ public function __construct(array $config) { parent::__construct('make:example', 'ドキュメントの例を作成', $config); $this->argument('<funny-gif>', '面白いGIFの名前'); } /** * 関数を実行 * * @return void */ public function execute(string $controller) { $io = $this->app()->io(); $io->info('例を作成します...'); // ここで何かを実行 $io->ok('例が作成されました!'); } }
独自のカスタムコマンドをFlightアプリケーションに組み込む方法については、adhocore/php-cliドキュメントを参照してください!
これはFlightを使いやすくするための拡張機能セットです。
$_SESSION
これはパネルです
それぞれのパネルはアプリケーションについて非常に役立つ情報を表示します!
ここをクリックしてコードを表示します。
composer require flightphp/tracy-extensions --dev を実行して、準備が整います!
composer require flightphp/tracy-extensions --dev
これを開始するために行う必要がある設定は非常に少ないです。これを使用する前に Tracy デバッガを初期化する必要があります https://tracy.nette.org/en/guide:
<?php use Tracy\Debugger; use flight\debug\tracy\TracyExtensionLoader; // ブートストラップコード require __DIR__ . '/vendor/autoload.php'; Debugger::enable(); // Debugger::enable(Debugger::DEVELOPMENT) で環境を指定する必要があるかもしれません // アプリでデータベース接続を使用する場合、 //(本番環境ではなく開発環境でのみ使用)必要なPDOラッパーがあります // 通常のPDO接続と同じパラメーターを持っています $pdo = new PdoQueryCapture('sqlite:test.db', 'user', 'pass'); // またはFlightフレームワークにこれをアタッチする場合 Flight::register('db', PdoQueryCapture::class, ['sqlite:test.db', 'user', 'pass']); // クエリを実行するたびに、時間、クエリ、およびパラメーターがキャプチャされます // これが全体を結びつけます if(Debugger::$showBar === true) { // これは false にする必要があります、さもないとTracy が実際にレンダリングできません :( Flight::set('flight.content_length', false); new TracyExtensionLoader(Flight::app()); } // もっとコード Flight::start();
カスタムセッションハンドラー(例えばghostff/sessionなど)を持っている場合、 任意のセッションデータ配列をTracyに渡し、自動的に出力します。 TracyExtensionLoader コンストラクターの第二パラメーターで session_data キーで渡します。
TracyExtensionLoader
session_data
use Ghostff\Session\Session; require 'vendor/autoload.php'; $app = Flight::app(); $app->register('session', Session::class); if(Debugger::$showBar === true) { // これは false にする必要があります、さもないとTracy が実際にレンダリングできません :( Flight::set('flight.content_length', false); new TracyExtensionLoader(Flight::app(), [ 'session_data' => Flight::session()->getAll() ]); } // ルートやその他のもの... Flight::start();
プロジェクトにLatteがインストールされている場合、 テンプレートを分析するためのLatteパネルを使用できます。 TracyExtensionLoader コンストラクターの第二パラメーターで latte キーでLatteインスタンスを渡すことができます。
latte
use Latte\Engine; require 'vendor/autoload.php'; $app = Flight::app(); $app->register('latte', Engine::class, [], function($latte) { $latte->setTempDirectory(__DIR__ . '/temp'); // これでLatte PanelをTracyに追加します $latte->addExtension(new Latte\Bridges\Tracy\TracyExtension); }); if(Debugger::$showBar === true) { // これは false にする必要があります、さもないとTracy が実際にレンダリングできません :( Flight::set('flight.content_length', false); new TracyExtensionLoader(Flight::app()); }
Tracy は Flight と一緒に使用できる素晴らしいエラーハンドラです。アプリケーションのデバッグに役立つ数々のパネルがあります。拡張して独自のパネルを追加するのも非常に簡単です。Flight チームは、flightphp/tracy-extensions プラグイン用にいくつかのパネルを作成しました。
Composer でインストールします。Tracy は本番用のエラーハンドリングコンポーネントが付属しているため、実際には dev バージョンなしでインストールする必要があります。
composer require tracy/tracy
開始するための基本的な設定オプションがあります。詳細については、Tracy ドキュメント を参照してください。
require 'vendor/autoload.php'; use Tracy\Debugger; // Tracy を有効にする Debugger::enable(); // Debugger::enable(Debugger::DEVELOPMENT) // 明示する必要がある場合もあります(Debugger::PRODUCTION も同様) // Debugger::enable('23.75.345.200'); // IP アドレスの配列を提供することもできます // ここにエラーと例外が記録されます。このディレクトリが存在し、書き込み可能であることを確認してください。 Debugger::$logDirectory = __DIR__ . '/../log/'; Debugger::$strictMode = true; // すべてのエラーを表示 // Debugger::$strictMode = E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED; // ディプリケートされた通知を除くすべてのエラー if (Debugger::$showBar) { $app->set('flight.content_length', false); // Debugger バーが表示されている場合、Flight によって content-length が設定できません。 // これは Flight 用の Tracy 拡張機能に固有のものです。これを含めた場合は有効にしてください。 new TracyExtensionLoader($app); }
コードのデバッグ中に、データを出力するための非常に役立つ関数がいくつかあります。
bdump($var)
dumpe($var)
アクティブレコードは、データベースエンティティをPHPオブジェクトにマッピングするものです。つまり、データベースにusersテーブルがある場合、そのテーブルの行をUserクラスと$userオブジェクトに「翻訳」することができます。基本的な例を参照してください。
User
$user
GitHubのリポジトリはこちら。
次のテーブルがあると仮定しましょう。
CREATE TABLE users ( id INTEGER PRIMARY KEY, name TEXT, password TEXT );
これを表す新しいクラスを設定できます。
/** * アクティブレコードクラスは通常単数形 * * ここにテーブルのプロパティをコメントとして追加することを強くお勧めします * * @property int $id * @property string $name * @property string $password */ class User extends flight\ActiveRecord { public function __construct($database_connection) { // この方法で設定できます parent::__construct($database_connection, 'users'); // またはこの方法で parent::__construct($database_connection, null, [ 'table' => 'users']); } }
さて、魔法が起こります!
// sqlite用 $database_connection = new PDO('sqlite:test.db'); // これは例です。実際はリアルなデータベース接続を使用するはずです // mysql用 $database_connection = new PDO('mysql:host=localhost;dbname=test_db&charset=utf8bm4', 'ユーザ名', 'パスワード'); // またはmysqli用 $database_connection = new mysqli('localhost', 'ユーザ名', 'パスワード', 'test_db'); // オブジェクトではないベースのmysqliでも $database_connection = mysqli_connect('localhost', 'ユーザ名', 'パスワード', 'test_db'); $user = new User($database_connection); $user->name = 'Bobby Tables'; $user->password = password_hash('some cool password'); $user->insert(); // または $user->save(); echo $user->id; // 1 $user->name = 'Joseph Mamma'; $user->password = password_hash('some cool password again!!!'); $user->insert(); // ここでは $user->save() を使用するとアップデートと認識されるので使用できません! echo $user->id; // 2
そして新しいユーザーを追加するのはこれだけでした!データベースにユーザー行があるので、それを取り出すにはどうすればよいでしょうか?
$user->find(1); // データベース内のid = 1を見つけてそれを返します。 echo $user->name; // 'Bobby Tables'
そしてすべてのユーザーを見つけたい場合はどうでしょうか?
$users = $user->findAll();
特定の条件で見つける場合はどうでしょうか?
$users = $user->like('name', '%mamma%')->findAll();
この楽しさがわかりますか?インストールして始めましょう!
Composerで簡単にインストールできます
composer require flightphp/active-record
これはスタンドアロンライブラリとして使用するか、Flight PHPフレームワークと一緒に使用できます。完全にあなた次第です。
単にコンストラクタにPDO接続を渡せばOKです。
$pdo_connection = new PDO('sqlite:test.db'); // これは例です。実際はリアルなデータベース接続を使用するはずです $User = new User($pdo_connection);
Flight PHPフレームワークを使用している場合は、ActiveRecordクラスをサービスとして登録できますが、必ずしも登録する必要はありません。
Flight::register('user', 'User', [ $pdo_connection ]); // その後は、コントローラや関数などでこれを使うことができます。 Flight::user()->find(1);
runway
runwayは、このライブラリ用にカスタムコマンドを持つFlight用のCLIツールです。
# 使用方法 php runway make:record データベースのテーブル名 [クラス名] # 例 php runway make:record users
これにより、app/records/ディレクトリにUserRecord.phpという新しいクラスが作成され、次の内容が含まれます。
UserRecord.php
<?php declare(strict_types=1); namespace app\records; /** * usersテーブル用のアクティブレコードクラス。 * @link https://docs.flightphp.com/awesome-plugins/active-record * * @property int $id * @property string $username * @property string $email * @property string $password_hash * @property string $created_dt */ class UserRecord extends \flight\ActiveRecord { /** * @var array $relations モデルの関係性を設定します * https://docs.flightphp.com/awesome-plugins/active-record#relationships */ protected array $relations = [ // 'relation_name' => [ self::HAS_MANY, 'RelatedClass', 'foreign_key' ], ]; /** * コンストラクタ * @param mixed $databaseConnection データベースへの接続 */ public function __construct($databaseConnection) { parent::__construct($databaseConnection, 'users'); } }
find($id = null) : boolean|ActiveRecord
1つのレコードを見つけて現在のオブジェクトに割り当てます。 $idを指定すると、その値で主キーを検索します。何も指定しない場合は、テーブル内の最初のレコードを検索します。
さらに、他のヘルパーメソッドを使ってテーブルをクエリできます。
// 事前に条件を指定してレコードを検索 $user->notNull('password')->orderBy('id DESC')->find(); // 特定のidでレコードを検索 $id = 123; $user->find($id);
findAll(): array<int,ActiveRecord>
指定したテーブル内のすべてのレコードを取得します。
$user->findAll();
isHydrated(): boolean
現在のレコードが取得済みかどうかを返します。
$user->find(1); // データが見つかった場合... $user->isHydrated(); // true
insert(): boolean|ActiveRecord
現在のレコードをデータベースに挿入します。
$user = new User($pdo_connection); $user->name = 'デモ'; $user->password = md5('デモ'); $user->insert();
テキストベースのプライマリキー(UUIDなど)を持っている場合、挿入前にプライマリキーの値を設定する方法が2つあります。
$user = new User($pdo_connection, [ 'primaryKey' => 'uuid' ]); $user->uuid = 'some-uuid'; $user->name = 'デモ'; $user->password = md5('デモ'); $user->insert(); // または $user->save();
または、イベントを使用してプライマリキーを自動生成することもできます。
class User extends flight\ActiveRecord { public function __construct($database_connection) { parent::__construct($database_connection, 'users', [ 'primaryKey' => 'uuid' ]); // このようにprimaryKeyを設定することもできます。上記の配列の代わりに $this->primaryKey = 'uuid'; } protected function beforeInsert(self $self) { $self->uuid = uniqid(); // またはユニークなIDを生成する方法に応じて } }
プライマリーキーを設定せずに挿入すると、rowidに設定され、データベースが生成しますが、それは持続しません。これはテーブルにそのフィールドが存在しないためです。これを自動的に処理するために、イベントを使用してください。
rowid
update(): boolean|ActiveRecord
現在のレコードをデータベースにアップデートします。
$user->greaterThan('id', 0)->orderBy('id desc')->find(); $user->email = 'test@example.com'; $user->update();
save(): boolean|ActiveRecord
現在のレコードをデータベースに挿入または更新します。レコードにidがある場合は更新し、そうでない場合は挿入します。
$user = new User($pdo_connection); $user->name = 'デモ'; $user->password = md5('デモ'); $user->save();
注意: クラス内で関係性が定義されている場合、それらの関係も再帰的に保存されます。関係が定義され、インスタンス化され、アップデートが必要なデータがある場合にのみです。 (v0.4.0以降)
delete(): boolean
現在のレコードをデータベースから削除します。
$user->gt('id', 0)->orderBy('id desc')->find(); $user->delete();
検索を実行してから複数のレコードを削除することもできます。
$user->like('name', 'Bob%')->delete();
dirty(array $dirty = []): ActiveRecord
データの変更された箇所をdirtyと呼びます。
$user->greaterThan('id', 0)->orderBy('id desc')->find(); // この時点では何も"dirty"はありません。 $user->email = 'test@example.com'; // これでemailは"dirty"と見なされる $user->update(); // 変更されたデータが保存されたため、今はdirtyなデータはありません $user->password = password_hash()'newpassword'); // これはdirtyです $user->dirty(); // 何も渡さないとすべてのdirtyエントリーがクリアされます。 $user->update(); // 何も変更されていないため、何も更新されません $user->dirty([ 'name' => 'something', 'password' => password_hash('a different password') ]); $user->update(); // nameとpasswordの両方が更新されます
copyFrom(array $data): ActiveRecord
これはdirty()メソッドのエイリアスです。何を行なっているかが少しだけわかりやすいです。
dirty()
$user->copyFrom([ 'name' => 'something', 'password' => password_hash('a different password') ]); $user->update(); // nameとpasswordの両方が更新されます
isDirty(): boolean
この現在のレコードが変更されている場合はtrueを返します。
$user->greaterThan('id', 0)->orderBy('id desc')->find(); $user->email = 'test@email.com'; $user->isDirty(); // true
reset(bool $include_query_data = true): ActiveRecord
現在のレコードを初期状態にリセットします。これはループ型の動作で使用するのに非常に役立ちます。 trueを渡すと、現在のオブジェクトを見つけるために使用したクエリデータもリセットされます(デフォルト動作)。
$users = $user->greaterThan('id', 0)->orderBy('id desc')->find(); $user_company = new UserCompany($pdo_connection); foreach($users as $user) { $user_company->reset(); // クリーンな状態で開始 $user_company->user_id = $user->id; $user_company->company_id = $some_company_id; $user_company->insert(); }
getBuiltSql(): string
find()、findAll()、insert()、update()、またはsave()メソッドを実行した後、構築されたSQLを取得し、デバッグ目的で使用できます。
find()
findAll()
insert()
update()
save()
select(string $field1 [, string $field2 ... ])
テーブル内の特定の列だけを選択できます(多くの列がある場合などに効果的です)。
$user->select('id', 'name')->find();
from(string $table)
別の表を選択することもできます。
$user->select('id', 'name')->from('user')->find();
join(string $table_name, string $join_condition)
データベース内の他のテーブルにジョインすることも可能です。
$user->join('contacts', 'contacts.user_id = users.id')->find();
where(string $where_conditions)
カスタムのwhere引数を設定できます(このwhere文内ではパラメータを設定できません)
$user->where('id=1 AND name="demo"')->find();
セキュリティ注意 - $user->where("id = '{$id}' AND name = '{$name}'")->find();のようなことをしたくなるかもしれません。絶対にこれをしないでください!これはSQLインジェクション攻撃に対して脆弱です。インターネットに多くの記事があるので、オンラインで「SQLインジェクション攻撃 PHP」と検索してみてください。このライブラリを使用する場合、このwhere()メソッドではなく、$user->eq('id', $id)->eq('name', $name)->find();のようにするのが適切です。必要な場合にのみ、PDOライブラリには$pdo->quote($var)があり、あなたに代わってエスケープしてくれます。quote()を使用してからwhere()ステートメント内で使用できます。
$user->where("id = '{$id}' AND name = '{$name}'")->find();
where()
$user->eq('id', $id)->eq('name', $name)->find();
$pdo->quote($var)
quote()
group(string $group_by_statement)/groupBy(string $group_by_statement)
結果を特定の条件でグループ化します。
$user->select('COUNT(*) as count')->groupBy('name')->findAll();
order(string $order_by_statement)/orderBy(string $order_by_statement)
クエリ結果を特定の方法でソートします。
$user->orderBy('name DESC')->find();
limit(string $limit)/limit(int $offset, int $limit)
返されるレコード数を制限します。2番目のintを指定すると、オフセットとリミットがSQLと同
ラッテ は、非常に使いやすく、Twig や Smarty よりも PHP 構文に近いテンプレートエンジンです。フル機能を備えており、独自のフィルタや関数を追加することも非常に簡単です。
Composer を使用してインストールします。
composer require latte/latte
始めるための基本的な設定オプションがあります。ラッテドキュメント で詳細を確認できます。
use Latte\Engine as LatteEngine; require 'vendor/autoload.php'; $app = Flight::app(); $app->register('latte', LatteEngine::class, [], function(LatteEngine $latte) use ($app) { // ここがラッテがテンプレートをキャッシュして処理を高速化する場所です // ラッテの素晴らしい点の1つは、テンプレートを変更すると自動的にキャッシュを更新します! $latte->setTempDirectory(__DIR__ . '/../cache/'); // ビューのルートディレクトリを示す Latte の設定 // $app->get('flight.views.path') は config.php ファイルで設定されています // または `__DIR__ . '/../views/'` のようなものも行えます $latte->setLoader(new \Latte\Loaders\FileLoader($app->get('flight.views.path'))); });
以下はレイアウトファイルのシンプルな例です。このファイルは他のすべてのビューを囲むために使用されます。
<!-- app/views/layout.latte --> <!doctype html> <html lang="en"> <head> <title>{$title ? $title . ' - '}My App</title> <link rel="stylesheet" href="style.css"> </head> <body> <header> <nav> <!-- ここにナビゲーション要素が入ります --> </nav> </header> <div id="content"> <!-- これが魔法です --> {block content}{/block} </div> <div id="footer"> © 著作権 </div> </body> </html>
そして、コンテンツブロック内でレンダリングされるファイルがあります:
<!-- app/views/home.latte --> <!-- このファイルが layout.latte ファイル内にあることを Latte に伝えます --> {extends layout.latte} <!-- レイアウト内のコンテンツブロック内に表示されるコンテンツです --> {block content} <h1>ホームページ</h1> <p>アプリへようこそ!</p> {/block}
次に、この内容を関数またはコントローラ内でレンダリングする際には、次のように行います:
// シンプルなルート Flight::route('/', function () { Flight::latte()->render('home.latte', [ 'title' => 'ホームページ' ]); }); // もしくはコントローラを使用している場合 Flight::route('/', [HomeController::class, 'index']); // HomeController.php class HomeController { public function index() { Flight::latte()->render('home.latte', [ 'title' => 'ホームページ' ]); } }
ラッテを最大限に活用するための詳細については、Latte Documentation を参照してください。
Flightは非常に拡張性があります。Flightアプリケーションに機能を追加するために使用できるプラグインがいくつかあります。一部はFlightチームによって公式にサポートされており、他のものはスタートを切るのに役立つマイクロ/ライトライブラリです。
認証と承認は、誰が何にアクセスできるようにするかを制御する必要があるアプリケーションにとって重要です。
キャッシュはアプリケーションの高速化に役立ちます。Flightと使用できるキャッシングライブラリがいくつかあります。
CLIアプリケーションはアプリケーションと対話する素晴らしい方法です。これらを使用してコントローラーを生成したり、すべてのルートを表示したりすることができます。
Cookieはクライアント側に小さなデータを保存するのに適した方法です。ユーザーの設定、アプリケーション設定などを保存するために使用できます。
ローカル環境で開発している場合、デバッグは重要です。デバッグ体験を向上させるプラグインがいくつかあります。
データベースはほとんどのアプリケーションの中核です。これによりデータを保存および取得できます。一部のデータベースライブラリは、クエリを記述するための単なるラッパーであり、一部は完全なORMです。
機密データを保存するアプリケーションにとって、暗号化は重要です。データの暗号化と復号は非常に難しくありませんが、暗号化キーを適切に保存することは困難です。暗号化キーを公開ディレクトリに保存したり、コードリポジトリにコミットしたりしないように注意することが最も重要です。
セッションはAPIにとってはあまり役立ちませんが、ウェブアプリケーションを構築する際には状態を維持し、ログイン情報を保持するために重要になります。
テンプレートはUIを持つ任意のウェブアプリケーションの中核です。Flightと組み合わせて使用できるいくつかのテンプレートエンジンがあります。
共有したいプラグインがありますか?リストに追加するためのプルリクエストを送信してください!
私たちは、Flight に関するインターネット上のさまざまなメディアの種類を追跡しようとしています。以下に、Flight についてもっと学ぶために使用できるさまざまなリソースを示します。
Flightを始めるには2つのオプションがあります:
これらはFlightチームによって公式にスポンサーされているわけではありませんが、Flightで構築された自分のプロジェクトを構造化する方法についてアイデアを与えるかもしれません!
共有したいプロジェクトがある場合は、このリストに追加するためのプルリクエストを送信してください!
システムにPHPがインストールされていることを確認してください。されていない場合は、システムにインストールする方法についてはこちらをクリックしてください。
Composerを使用している場合は、次のコマンドを実行できます:
もしくはファイルをダウンロードして、それらをウェブディレクトリに直接展開します。
これは最も簡単に立ち上げる方法です。組み込みサーバーを使用してアプリケーションを実行したり、SQLiteをデータベースとして使用したりすることができます(システムにsqlite3がインストールされている限り)、そして多くのものを必要としません! PHPがインストールされたら、次のコマンドを実行してください:
php -S localhost:8000
その後、ブラウザを開いてhttp://localhost:8000に移動します。
http://localhost:8000
プロジェクトのドキュメントルートを異なるディレクトリにする場合(例: プロジェクトが ~/myproject であるが、ドキュメントルートは ~/myproject/public/ である場合)、~/myproject ディレクトリにいる場合は、以下のコマンドを実行できます:
~/myproject
~/myproject/public/
php -S localhost:8000 -t public/
Apacheが既にシステムにインストールされていることを確認してください。されていない場合は、システムにApacheをインストールする方法をGoogleで調べてください。
Apacheの場合、.htaccess ファイルを次のように編集してください:
注意: サブディレクトリでflightを使用する必要がある場合は、RewriteEngine Onの直後に次の行を追加してください: RewriteBase /subdir/ 注意: dbやenvファイルなどのすべてのサーバーファイルを保護する必要がある場合は、.htaccess ファイルに次の内容を追加してください:
注意: サブディレクトリでflightを使用する必要がある場合は、RewriteEngine Onの直後に次の行を追加してください: RewriteBase /subdir/
注意: dbやenvファイルなどのすべてのサーバーファイルを保護する必要がある場合は、.htaccess ファイルに次の内容を追加してください:
Nginxが既にシステムにインストールされていることを確認してください。Nginxをインストールしていない場合は、システムにNginx Apacheをインストールする方法をGoogleで調べてください。
Nginxの場合、サーバー宣言に次の内容を追加してください:
<?php // Composerを使用している場合は、オートローダーを要求します。 require 'vendor/autoload.php'; // Composerを使用していない場合は、フレームワークを直接ロードしてください // require 'flight/Flight.php'; // 次にルートを定義し、リクエストを処理するための関数を割り当てます。 Flight::route('/', function () { echo 'hello world!'; }); // 最後に、フレームワークを起動します。 Flight::start();
すでにシステムに php がインストールされている場合は、この手順をスキップしてダウンロードセクションに移動してください
php
分かりました!macOS、Windows 10/11、Ubuntu、Rocky Linux にPHPをインストールする手順についての説明があります。さらに、異なるバージョンのPHPをインストールする方法についても説明します。