Prismaを使ってWordPressのデータベースにTypeScriptでアクセスする
Prismaでは、既存のDB情報からスキーマを作ることができます。 The db pull command connects to your database and adds Prisma models to your […]
目次
Prismaでは、既存のDB情報からスキーマを作ることができます。
The
db pull
command connects to your database and adds Prisma models to your Prisma schema that reflect the current database schema.https://www.prisma.io/docs/reference/api-reference/command-reference#db-pull
手持ちの稼働しているDBがWordPressのみでしたので、試しにつないでみました。
前準備
事前準備として、以下の作業を行います。
- MySQLでDBに接続するためのユーザーを用意する
- 事故防止のため、ユーザーはREAD権限のみにする
- WordPressのDBが入っているサーバー(Amazon EC2)に、ローカルPCからMySQLで接続できるようにする
Amazon EC2インスタンスに、MySQLで接続できるようにする
AMIMOTO AMIなどでWordPressを立ち上げた場合、デフォルトではインスタンスにはMySQLで接続できません。
セキュリティグループに、以下の情報を追加して、アクセスできるようにします。
{
"FromPort": 3306,
"IpProtocol": "tcp",
"IpRanges": [
{
"CidrIp": "xxx.xx.xx.xxx/32"
}
],
"Ipv6Ranges": [],
"PrefixListIds": [],
"ToPort": 3306,
"UserIdGroupPairs": []
},
MySQLで読み込み専用のユーザーを作成する
続いてDBを読むためのユーザーを作成します。
必要のないDBへアクセスさせたくないので、前もってデータベースの情報を確認します。
mysql> show databases;
+---------------------+
| Database |
+---------------------+
| information_schema |
| wp_db |
| mysql |
| performance_schema |
| sys |
+---------------------+
5 rows in set (0.00 sec)
WordPressの場合、wp-config.php
(AMIMOTOではlocal-config.php
)でもDB名は確認できます。
アクセスさせたいデータベースの名前を確認したら、ユーザーを作成しましょう。
mysql> CREATE USER 'nodejs'@'123.45.67.890' IDENTIFIED BY 'YOUR_PASSWORD';
mysql> GRANT SELECT ON wp_db.* TO 'nodejs'@'123.45.67.890' IDENTIFIED BY 'YOUR_PASSWORD' WITH GRANT OPTION;
パラメータはそれぞれ以下の通りです。
nodejs
: DBにアクセスするためのユーザー名123.45.67.890
: ユーザーのIPアドレス。今回は自分のIPを調べて設定YOUR_PASSWORD
: ユーザーのパスワードwp_db
: アクセスしたいデータベースの名前
PrismaでDBに接続するプロジェクトをセットアップする
ユーザーが作成できたので、Prismaで接続準備を始めます。
% mkdir wordpress
% cd wordpress
% npm init -y
% npm install typescript ts-node @types/node --save-dev
% touch tsconfig.json
% npm install prisma --save-dev
プロジェクトの作成後、セットアップコマンドを実行しましょう。
% npx prisma init --datasource-provider mysql
✔ Your Prisma schema was created at prisma/schema.prisma
You can now open it in your favorite editor.
Next steps:
1. Set the DATABASE_URL in the .env file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started
2. Run prisma db pull to turn your database schema into a Prisma schema.
3. Run prisma generate to generate the Prisma Client. You can then start querying your database.
More information in our documentation:
https://pris.ly/d/getting-started
DATABASE_URL
を環境変数で設定する必要があります。
.env
ファイルが生成されているので、自分のDB情報に書き換えましょう。
- DATABASE_URL="mysql://johndoe:randompassword@localhost:3306/mydb"
+ DATABASE_URL="mysql://nodejs:[email protected]:3306/wp_db"
PrismaでWordPressのDB設定をpullする
接続の設定ができていれば、あとはpullするだけです。
% yarn prisma db pull
yarn run v1.22.15
$ /Users/sandbox/sql/wordpress/node_modules/.bin/prisma db pull
Prisma schema loaded from prisma/schema.prisma
Environment variables loaded from .env
Datasource "db": MySQL database " wp_db" at "123.45.67.890:3306"
✔ Introspected 29 models and wrote them into prisma/schema.prisma in 4.54s
Run yarn prisma generate to generate Prisma Client.
✨ Done in 6.38s.
prisma/schema.prisma
の中身が、DATABASE_URL
に指定したDBの設定に合わせて変更されています。
model wp_postmeta {
meta_id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
post_id BigInt @default(0) @db.UnsignedBigInt
meta_key String? @db.VarChar(255)
meta_value String? @db.LongText
@@index([meta_key(length: 191)], map: "meta_key")
@@index([post_id], map: "post_id")
}
...
generate
コマンドを実行すると、クライアントコードに設定が反映されます。
% prisma generate
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
added 2 packages, and audited 24 packages in 16s
found 0 vulnerabilities
✔ Installed the @prisma/client and prisma packages in your project
✔ Generated Prisma Client (4.2.1 | library) to ./node_modules/@prisma/client in 365ms
You can now start using Prisma Client in your code. Reference: https://pris.ly/d/client
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
✨ Done in 19.67s.
PrismaでWordPressの情報を取得する
クライアントの設定が完了したので、実際にデータをよんでみましょう。
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
const main = async () => {
const post = await prisma.wp_posts.findFirst({
where: {
ID: 2458
}
})
return post
}
main().then(console.log).catch(console.log)
このコードは、IDで特定の投稿を取得するクエリです。
yarn ts-node ./PATH/TO/FILE.ts
などで実行すると、DBから結果が取得できます。
wp_postmetaの情報から記事を検索する
WordPressでクエリが複雑になりやすいケースの1つが、「特定のカスタムフィールド情報を持つ記事を取得する」です。
せっかくなので、これをPrismaで実装してみましょう。
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
const main = async () => {
const postsMeta = await prisma.wp_postmeta.findMany({
select: {
post_id: true,
meta_key: true,
meta_value: true,
},
where: {
OR: [{
meta_key: "meta_keywords",
meta_value: {
not: ""
}
},{
meta_key: {
contains: 'vkExUnit_cta'
},
meta_value: {
contains: 'Amazon'
},
}],
},
take: 50,
})
const posts = await prisma.wp_posts.findMany({
select: {
ID: true,
post_title: true,
},
where: {
ID: {
in: postsMeta.map(meta => meta.post_id)
}
}
})
return posts.map(post => {
const metaItems = postsMeta.filter(meta => meta.post_id === post.ID)
if (!metaItems) return post
return {
...post,
ID: post.ID.toString(),
post_meta: metaItems.map(item => {
return {
[item.meta_key]: item.meta_value
}
}),
}
})
}
main().then(data => {
console.log(JSON.stringify(data,null,2))
}).catch(console.log)
prisma.wp_postmeta
に対してfindMany
で検索をかけます。
その後、取得できたデータのpost_id
を使ってprisma.wp_posts
にクエリを投げて、記事を取得しています。
最後に、postmeta
の情報をpost
に追加して表示させましょう。
このように情報が取得できます。
[
{
"ID": "123",
"post_title": "WordPressサイトの「ドメイン」の話",
"post_meta": [
{
"meta_keywords": "ドメイン"
}
]
},
{
"ID": "456",
"post_title": "サーバーレスシングルページアプリケーション",
"post_meta": [
{
"vkExUnit_cta_button_text": "Amazonで買う"
},
...
使い道
「Prisma使ってみたい」と「手持ちのDBがWordPressだった」の2つから始まったので、実用的かといわれるとちょっと悩ましいです。
Amazon RDSなどでデータを管理している場合は、VPC Lambdaを使ってWordPressのDB情報を取得するのに使えるかもしれません。あとは複雑なクエリをもつAPIを、WordPressの知識なしに実現させたい場合や、すでにPrismaを使っているアプリでWordPressのDB情報も参照したい場合・・・などでしょうか。
WooCommerceを入れている場合は、顧客や注文情報のクエリにも使えるかもしれません。