ユーティリティライブラリ

すべてのユーティリティは static メソッドで構成され、外部依存はありません。名前空間は _Flexagon\Libs です。

クラス 主な機能
StringUtil 大文字・小文字の変換、UTF-8 のクリーンアップ、16 進エンコード、ランダム文字列の生成
ArrayUtil キーの camelCase 変換、配列の差分、ネストした配列のキー検索
ValidUtil メールアドレス、整数、浮動小数点数、英数字、ID の検証
CryptoUtil AES-256-CBC による暗号化・復号(カラム向けの決定的な encryptString()、文字列・配列向けのランダム IV による encrypt())
FileUtil ディレクトリの走査、再帰的な作成、拡張子の判定
HttpUtil URL の解析、クエリ文字列の解析、リクエストパスの解決
NetUtil GET/POST の HTTP クライアント、JSON レスポンスの解析、ファイルのアップロード
HtmlUtil リダイレクト、HTML タグ・属性の除去、画像 URL の抽出
TimeDateUtil タイムスタンプの変換、タイムゾーンのオフセット、相対時間のフォーマット
SqlUtil パラメーターの正規化・展開、SQL のエスケープ、SELECT → COUNT の変換
ClassUtil クラス名、パス、プロパティ、呼び出し元の調査
PhpDocUtil PHPDoc タグの解析(アノテーションサポートの基盤)
AssetLoader CSS/JS の管理
TemplateLoader テンプレートの読み込み
DataSourceManager 接続の再利用とグローバルトランザクション
Env 環境変数と .env.php からの設定値・シークレット

グローバルヘルパー関数

Libs/_Util.php で定義されている 3 つの関数は、名前空間なしでグローバルに利用できます。

_echo('Hello, {name}', ['name' => $user->getName()]);   // 置換して出力
$msg = _t('{count} results found', ['count' => 42]);    // 置換して返す

___() は _t() のエイリアスです。プレースホルダーの置換は 1 回のパスで行われるため、値そのものに {name} が含まれていても、再度置換されることはありません。

翻訳(I18n)

これらのヘルパーは、プレースホルダーを置換する前に、_Flexagon\I18n\Translator に登録されたトランスレーターでメッセージを翻訳します。トランスレーターが登録されていない場合は、元のメッセージがそのまま使われます。

トランスレーターは 1 つのメソッドを実装します。

namespace _Flexagon\I18n;

interface TranslatorInterface
{
    public function translate(string $message): string;
}

リクエストの早い段階(public/_entry.php または application/_Config.php)で一度だけ登録します。

// public/_entry.php
use _Flexagon\I18n\Translator;

setlocale(LC_MESSAGES, 'ko_KR.UTF-8');
bindtextdomain('messages', LOCALE_ROOT);
textdomain('messages');

Translator::setTranslator(new \I18n\GettextTranslator());

スケルトンには、application/I18n/ に 3 つのアダプターのサンプルが同梱されています。

クラス 翻訳に使用するもの 必要なもの
GettextTranslator gettext() ext-gettext
MoTranslator __() __() を定義するライブラリ(例:.mo リーダー)
SymfonyTranslator trans() symfony/translation
Translator::setTranslator(new \I18n\SymfonyTranslator($symfonyTranslator));

LOCALE_ROOT のデフォルトは PROJECT_ROOT . '/locale' です。変更する場合は、フレームワークの起動前に define() してください。

次の点に注意してください。

  • 出力はエスケープされません。 _echo() は翻訳・置換された文字列をそのまま出力します。ユーザーが入力した値は、渡す前に htmlspecialchars() でエスケープし、翻訳カタログは信頼できる HTML ソースとして扱ってください。
  • トランスレーターはプロセス単位の static です。 これは、リクエストごとにクリーンな状態から始まる PHP-FPM のモデルに適しています。長時間稼働するワーカー(Swoole、RoadRunner、FrankenPHP のワーカーモード)では、リクエストごとにトランスレーターを再登録してください。setlocale() はプロセス全体に作用し、スレッドセーフではありません。
  • コストはアダプターによって決まります。 フレームワーク自体のオーバーヘッドは 1 回の呼び出しあたり約 0.3 µs です。gettext はプロセスごとに .mo ファイルをキャッシュします(更新後は PHP-FPM を再起動してください)。一部の .mo ライブラリはリクエストのたびにファイルを解析します。Symfony Translation は、cache_dir を設定しない限りリクエストごとにカタログを再読み込みします。

Enum ヘルパー

backed enum に EnumSupporter トレイトを追加すると、便利なメソッドが使えるようになります。

use _Flexagon\Supporters\EnumSupporter;

enum UserRole: string {
    use EnumSupporter;

    case ADMIN = 'ADMIN';
    case USER  = 'USER';
}

UserRole::keys();            // ['ADMIN', 'USER']
UserRole::values();          // ['ADMIN', 'USER']
UserRole::toArray();         // ['ADMIN' => 'ADMIN', 'USER' => 'USER']
UserRole::toCommaString();   // 'ADMIN,USER'

ENUM カラムの DDL を生成する場合は、toQuotedCommaString() を使用してください。各値をクォートで囲み、値に含まれるクォートは二重にしてエスケープします。

UserRole::toQuotedCommaString();      // "'ADMIN','USER'"
UserRole::toQuotedCommaString('"');   // '"ADMIN","USER"'

// 値にクォートやカンマが含まれていても安全
// case A = "it's";  case B = 'a,b';
//   toCommaString()        → it's,a,b          (DDL が壊れる)
//   toQuotedCommaString()  → 'it''s','a,b'

値を持たない pure enum の場合、keys() と toCommaString() はケース名を返し、values() と toArray() の値は null になります。

Enum 型のプロパティは、DAO のマッピングでも自動的に処理されます。モデルへのハイドレーション時にはデータベースのスカラー値が対応する enum ケースに変換され、保存時には ->value がバインドされます。