TehilimというPrismaみたいなPHPのデータベースライブラリを作った
RelayerというPHPのWebフレームワークに続いてTehilimというPrismaみたいなPHPのデータベースライブラリを作った。 https://github.com/polidog/tehilim
モチベーション
PHPのDB周りのライブラリ(ORM)は基本WebフレームワークにくっついてくるDoctrineやEloquentなどのクラスベースなライブラリばかりだった。
ただ、本当にそれでいいのか?Prismaを使ったときの心地よさもあったので、それをPHPで再現したいところから開発をスタートさせた。
特徴
Tehilimは以下の特徴を持つ
- PrismaみたいにスキーマをもとにDBを構成する
- マイグレーションサポート
- 全てはArrayである
Prismaみたいなスキーマを元にDBを構成する
$ vendor/bin/tehilim init
これだけで、tehilimというディレクトリが作成されて、そのなかに tehilim.schema というスキーマファイルが生成される。
ほぼPrismaのスキーマと同じ。
datasource db {
provider = "sqlite"
url = "sqlite:./dev.sqlite"
}
generator client {
output = "./src/Generated"
namespace = "App\\Generated"
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
createdAt DateTime @default(now())
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
body String?
published Boolean @default(false)
authorId Int
author User @relation(fields: [authorId], references: [id])
createdAt DateTime @default(now())
}
マイグレーションサポート
スキーマでテーブルの定義を書いたら
$ vendor/bin/tehilim migrate dev
と実行したらマイグレーションファイルが生成されてマイグレーションが実行される。
この辺はPrismaと全く一緒。
全てはArrayである
DoctrineだったりEloquentだったりPHPのORMはすべてクラスベースな仕組みだけど、Tehilimは違う。
PHPの多くのライブラリはデータベースから値を取得してその結果をオブジェクト(クラス)にマッピングするが、Tehilimは配列で返す。
(まあ大体のライブラリはArrayにマッピングすることもできるが、選択するのは稀だと思う。)
配列にマッピングすると静的検査がしづらくなる問題が発生する。
たとえば以下のようにデータベースを検索した場合に、arrayであることはPHPStanでチェックできるが、id, email 以外のプロパティに触ったときにPHPStanで検知することは通常ではできない。
$user = $db->user->findFirst([
'select' => ['id', 'email'],
]);
しかしTehilimではPHPStanの拡張を作ることでその問題を解決した。
https://github.com/polidog/tehilim#phpstan-extension
個人的にもずっとクラスにマッピングするのはほぼ型がほしいからだけであって、クラスとして扱いたいということが少なかった。
データを受け取った情報として定義したいクラスはあるが、DBから取得した値は単純な配列でよかった。問題は静的なチェックが出来ないことだけだったので、この対応はなかなかいいのではないかと思う。
Relayerとの連携
もちろんRelayerを通じて使うことを想定している。 そのために「Request-scoped cache」や「プロファイラ」のサポートもいれている。
https://github.com/polidog/tehilim#request-scoped-cache https://github.com/polidog/tehilim#profiler-hook
最後に
AI時代になって、欲しいと思えるものが低コストで作れるようになった。
ただし安定させるのはやはり難しい。
ただRelayerもそうだけど、こういったライブラリを作ることはやっぱり意味があるのでRelayer同様に安定版リリースできるように開発を進めていきたい。