Pods: 学習しながらまとめているページ

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句にパラメーターを渡すことは現段階ではできないようです。

そしてまだまだ更新が続く…