WordPressを使ってWebアプリを作る際にPodsを利用することにしました。
Podsについてまだ勉強中なのと、日本語で書かれた情報が少ないので、ここで調べたことをメモとして随時更新していきます。
完全に自分用の学習メモを公開しているだけなので、”超読みづらい”です。
なので、「読みにくいぞ!コラー」って文句言わないようにお願いします
まずはPodsについて簡単に説明
WordPressで独自のテーブルを作りたい時は、実際にテーブルを作るのではなく、カスタム投稿タイプを使ってwp_postsテーブルのpost_typeを新規に作ることで対応するのが基本となります。
例)注文テーブルが欲しい
×:orderテーブルを作る
○:post_typeにorderを追加する
ただし、この方法だとwp_postsテーブル内に必要なカラムを追加できないので、wp_postsテーブルに紐づくwp_postmetaテーブルを利用することになります。
例えば注文テーブルに購入者(purchaser)というカラムを持たせたいような場合だと、post_typeがorderとして作成したデータのIDを持つkeyがpurchaserというデータをwp_postmetaテーブルに作成します(言葉にするとややこしい)。
次に新規で作成したカスタム投稿タイプに、データを登録するための登録画面を作成する必要があります。
(ここまでの作業について詳しくはこちらのスライドの65ページ目からがわかりやすいです。)
ここまでの流れを実装するのはとても手間がかかりますが、Podsを使うとこれらの作業が劇的に楽になります。
例えばpodsで新規作成を行うと、上記のことがPHPのコードを書くことなくWebページ上でまるで新規テーブルを作っているかの様に自然に行うことができます。つまりpost_typeやmetaテーブルのことを気にしないで済みます。さらに登録画面も自動で生成してくれるので、コーティングなしで新規で追加したポストタイプのCRUDができるようになります。
■2019年6月追記
Podsの使い方を動画で解説しました。
こちらも合わせてご覧ください。
WordPressとPodsで好きなデータを簡単に保存する方法を動画で解説
独自テーブルについて
PodsではAdvanced Contet Types(以降、ACT)という拡張機能を利用して新規テーブルを作ることも可能ですが、この拡張機能はデフォルトではオフになっています。またComponentsページでは、ACTよりはカスタムコンテントタイプの利用を強く推奨されています。
You most likely don’t need these and we strongly recommend that you use Custom Post Types or Custom Taxonomies instead.
また、WordPressでWebアプリを作るときは既存テーブルがいいのか?カスタムテーブルがいいのか?にもカスタムコンテントタイプのテーブルを利用したほうがいい理由をまとめているのでご覧ください。
ACTにはデータを表示するためのPods Pagesも用意されています。
http://pods.io/tutorials/using-pods-pages-advanced-content-types/
ただし、Pods PagesはACTと一緒に使うことが前提となっています。
Pods Pages are used to display content from Advanced Content Types (ACTs) and should only be used with Advanced Content Types.
カスタム投稿タイプを作る
作成したカスタム投稿タイプのExport/Import
カスタム投稿タイプを開発環境で作った後に、同じ設定をテスト環境や本番環境に行う必要がありますが、これを手動で行うのは手間がかかりますし、ミスも起こりやすくなります。
そこでComponentsの中にあるMigrate: Packagesを利用すると、設定した内容を手間なくミスなくExport/Importできるようになります。
メモ
※フロントエンドに表示されないようにする場合は、Publicly Queryableのチェックを外す。ただしプレビューも行えなくなるので注意が必要。その他の設定項目の詳細はこのページを参照のこと。
※Custom User Capabilityを設定した場合は、Administrator権限でも管理画面のメニューに作成したカスタム投稿タイプが表示されなくなる。Roles & Capabilitiesを有効化して、administratorに作成したpost_typeに関する権限をONにする必要がある。
※値がユニークであるかのバリデーションはこのスレッドによるとまだ実装されていない模様。
フロントエンドでの表示
登録したデータをフロントエンド側で表示するためには、Pods TemplateとMagic tagsを利用すると簡単に実現できます。
Pods Template
http://pods.io/tutorials/how-tos-sceencasts-series/using-pods-templates-part-1/
http://pods.io/docs/code/pods/template/
Magic tags
http://pods.io/docs/build/using-magic-tags/
メモ
※{@field_name,esc_attr} or {@field_name,esc_html} とすれば、アウトプットのサニタイジングも可能(らしい)
データの抽出
データの絞り込みはfindを使います。
日付での絞り込み例
$todays_date = date('Y/m/d'); $pod = pods( 'order' ); $params = array('where' => "Date(start_dt.meta_value) > '" . $todays_date . "'"); $pod->find( $params );
findの結果が複数行ある場合の結果の取得方法
dataを利用すると結果を配列として取得できます。ただしACTの場合、リレーションシップフィールドは配列に含まれないので注意が必要です。
fetchを使うと全てのデータが取得できるので、こちらの方が無難でしょう。
リレーションシップフィールドをwhereに含める場合
SELECTするテーブルにリレーション先となるテーブルのID(下の例ではclikent_id)を持っている場合は
‘where’ => “t.client_id = 7”
のように記述できます。
しかしリレーションシップフィールドとして定義している場合(下の例ではclientというテーブルがリレーションシップフィールド)は、以下のように記述する必要があります。
‘where’ => “client.id = 7”
Group by
Group byを使う場合は以下のようにselectとgroupbyをセットで記述します。
$params = array( 'select' => "t.id, sum(t.amount) as total", 'groupby' => "id", ); $pod = pods( 'results' ); $pod->find( $params );
formを使ったデータの登録
Podsのformを使うと管理画面からだけではなく、フロントエンドからもデータの登録を行うことが簡単に可能になります。
登録前に入力値をバリデーションしたり、登録と同時に他の処理も実行したいといったときには、フィルターとアクションを使えば実現可能です。
編集したいフィールドの指定
画面上で編集したいフィールドはform関数の第一パラメーターに配列として渡します。
例:
echo $mypod->form(); $fields = array( 'name', 'description' => array( 'type' => 'paragraph', 'label' => 'Special Label' ), 'other' ); echo $mypod->form( $fields );
※必須項目にするためには’required’ => trueと設定する。
※hiddenフィールドにするためには’hidden’ => true、もしくは’type’ => ‘hidden’にする。
※デフォルト値をセットするには’default’ => を使う
表示する項目を絞り込みたい場合
Podsの編集画面のAdditional Field Options内のCustomized WHEREにWHERE句を指定することで絞り込みができます。
例:t.client_id = 7
上記の7の部分を動的に替えたい場合はSpecial Magic Tagsが使えます。
例:t.client_id = {@url-relative.1}
Special Magic Tagsの詳細はこちらをご覧ください。
ただしこの方法を使うと管理者画面では設定したカラムがSQLエラーとなることがあるので注意が必要です。
データの保存や削除に関連したフィルターとアクション
こちらにデータの保存や削除を実行した際にフックされているフィルターとアクションがまとまっています。
そしてこれらのフィルターやアクションに渡されるパラメーターの中身はこのページで説明されています。
この中で曲者なのが$pieces[ ‘fields_active’ ]です。
ここに登録されているフィールドしか、データ更新時にDBに反映されないので注意が必要です。
[fields_active] => Array ( [0] => price [1] => owners )
↑の場合はpriceフィールドとownersフィールドのみ、DB内のデータが更新されます。
$pieces[ ‘fields_active’ ]に配列を追加する例はこのページで紹介されています。
※この方法はpost_titleには使えません。こちらのスレッドによると、
pods_api_pre_save_pod_item does not work because $pieces[‘fields’] only refers to custom meta fields. The default post fields such as ‘post_title’ are only found in: $pieces[‘object_fields’]. However, these only appear to be field descriptors because there is no ‘value’ property to any of these fields.
とのことです。
同じ回答の中にハックする方法が書いてありますが、これは管理画面からの投稿には使えますが、formを使った場合には$postarr[ ‘pod_meta_%my_meta_name%’]が存在しないので機能しません。
データのデバッグ
formを使った際のデータ処理はAJAXで行われるためデバッグが困難です。
一番簡単なのは、return pods_error( ‘Here is your error message’ );を使う方法です。ただこれだとecho的な使い方しかできないので、複雑なデバッグには向いていません。
先ほど紹介したページの後半にデバッグ用のコードが提供されているのでそれを利用するのがいいでしょう。
ちなみに私はデバッグにはWP PHP Consoleを使っています。
データのバリデーション
データのバリデーション:
実装例
Best way to validate and output form validation error
メモ
※formを使った場合、カスタム投稿タイプに設定したユーザー権限に関係なくデータを編集できてしまうので注意が必要(例:edit_posts権限がなくてもポストできてしまう)。formを使っているページのコードで権限ごとに書き分ける必要がある。
※必須項目としたフィールドが空のままsubmitすると、(フィールド名) is requiredの様に英語でエラーメッセージが表示されてしまう。これはJSでハードコーディングされているため。このページによると3.0で修正される模様。
formを使わないデータの登録
データの追加にはaddを使います。
データを一度に複数行追加するにはimportを使います。
データの更新にはsaveを使います。
リレーションシップフィールドへの追加にはadd_toを使います。
リレーションシップフィールドへの追加
Podsではリレーションシップは通常のRDBの外部キーを使うそれと異なり、リレーションシップ専用のテーブル(wp_podsrel)で管理しています。(詳細はこちら)
ACTのテーブルの場合は、リレーションシップフィールドが実テーブルに存在しないため、データの登録時に次の二段階を踏む必要があります。
1.リレーションシップフィールド以外のデータの保存
2.保存したデータに対してadd_to()でリレーションシップフィールドの追加
下記が例です。
この例ではresultsというテーブルにclientというリレーションシップフィールドがあると仮定しています。
//INSERTしたいデータ $data = array( 'year' => 2015, 'month' => 8, 'charge' => 100000, ); //INSERT対象のテーブルを準備 $pod = pods('results'); //データをINSERT $item_id = $pod->save($data); //INSERTしたデータを取得 $saved_pods = pods('results', $item_id); //リレーションシップフィールドであるclientにIDを登録 $saved_pods->add_to('client', 7);
管理画面からのデータの登録
カスタム投稿タイプを作成すると、管理画面からデータが登録できるようになります。
メモ
※Customized WHEREにSQLのWhere句を書くことでフィルターができますが、このスレッドによると、Where句にパラメーターを渡すことは現段階ではできないようです。