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を構成する

1
$ vendor/bin/tehilim init

これだけで、tehilimというディレクトリが作成されて、そのなかに tehilim.schema というスキーマファイルが生成される。 ほぼPrismaのスキーマと同じ。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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())
}

マイグレーションサポート

スキーマでテーブルの定義を書いたら

1
$ vendor/bin/tehilim migrate dev

と実行したらマイグレーションファイルが生成されてマイグレーションが実行される。
この辺はPrismaと全く一緒。

全てはArrayである

DoctrineだったりEloquentだったりPHPのORMはすべてクラスベースな仕組みだけど、Tehilimは違う。
PHPの多くのライブラリはデータベースから値を取得してその結果をオブジェクト(クラス)にマッピングするが、Tehilimは配列で返す。 (まあ大体のライブラリはArrayにマッピングすることもできるが、選択するのは稀だと思う。)

配列にマッピングすると静的検査がしづらくなる問題が発生する。
たとえば以下のようにデータベースを検索した場合に、arrayであることはPHPStanでチェックできるが、id, email 以外のプロパティに触ったときにPHPStanで検知することは通常ではできない。

1
2
3
$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同様に安定版リリースできるように開発を進めていきたい。

カテゴリ

comments powered by Disqus