JavaScriptPrisma / TypeORMWordPress

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:XXXXXXXX@123.45.67.890: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を入れている場合は、顧客や注文情報のクエリにも使えるかもしれません。

ブックマークや限定記事(予定)など

WP Kyotoサポーター募集中

WordPressやフロントエンドアプリのホスティング、Algolia・AWSなどのサービス利用料を支援する「WP Kyotoサポーター」を募集しています。
月額または年額の有料プランを契約すると、ブックマーク機能などのサポーター限定機能がご利用いただけます。

14日間のトライアルも用意しておりますので、「このサイトよく見るな」という方はぜひご検討ください。

広告ここから
広告ここまで

Related Category posts