はじめに
Laravelは使用するRDBMSを選択できるようになっていますので、ファイルタイプのSQLiteとかサーバータイプのMySQLとかでも同じような操作でORMができます。
しかし、RDBMS依存のものもあり、例えばストアドプロシージャやファンクションなどを呼び出す場合などに環境によって同じように動作しないケースもあります。
例えば本番環境ではMySQLを使っていて、ストアドファンクションを呼び出すようなコードがLaravelで作成しているプロジェクトに含まれているとします。
そして、開発環境ではDBにSQLiteを使っていたり、XAMPPのMariaDBだけどファンクションをまだ実装していなかったりするとき、そのコードは実行時エラーになります。
そういうときにDBがMySQLかつストアドファンクションを実装しているかどうかを取得できたらいいですよね。
今回はそのケースでの方法を紹介します。
実装例
今回はMySQL環境で指定した名前のストアドファンクションがあればtrueを返すユーティリティ関数を実装します。
例外処理などは省略しています。
class Util{
public static function hasStoredFunction(string $functionName): bool{
if(DB::getDriverName() !== 'mysql'){ return false; }
return DB::table('INFORMATION_SCHEMA.ROUTINES')
->where('ROUTINE_SCHEMA', DB::raw('DATABASE()'))
->where('ROUTINE_NAME', $functionName)
->where('ROUTINE_TYPE', 'FUNCTION')
->exists();
}
}
使用例
例えばLaravelでCRMとかを作っていて見積一覧のページを実装しているとする。
要件
- 本番環境のMySQLにはquotationsテーブルのレコードidを渡すとユニークな見積番号を生成するquotation_numberというファンクションが実装されている
- EloquentORMを使って、quotationsテーブルのデータをページネーションで取得する際に、quotation_numberファンクションがMySQL上にあれば、データと共に見積番号をq_numberとして取得する。MySQLじゃなかったりファンクションが実装されていなければ取得しない
というような場合の使用例。
//~~ 略 ~~
$q = Quotations::query();
$q->select('*');
if(Util::hasStoredFunction('quotation_number')){
$q->selectRaw('quotation_number(id) AS q_number');
}
return $q->paginate();
まとめ
- INFORMATION_SCHEMA.ROUTINESに自作したファンクションの情報がある。