Custom Field Suiteというプラグインが最近公開停止になって、ACFのリピーターフィールド機能が有料になって乗り換えたという人が悲鳴を上げているとかなんとか..。
そこでWordPressにおけるカスタムフィールドの繰り返しフィールドって何なの?コードを自作したらどんな風になるの?ということについて個人的見解と、ショートコードで投稿の末尾などに更新情報を載せるための機能を試しに作ってみたのでコードを公開しておきます。
まず、リピーターフィールドというのは、カスタムフィールドの複数のフィールドと値をグループにしたものを複数保存、呼び出しできる機能(個人的見解です)。
利用するシーンとしては、後程紹介するコードのように「日付」と「更新内容」がセットになったものを、メタボックス(カスタムフィールド管理用の入力フォームの意)を通じて次々に登録しておき、どこかに何等かの形(ショートコードなどを使って)一覧表示させるようなコンテンツを作りたい場合に使うのだと考えられます。
結論から言うと、今回の更新履歴のケースでは、テーブルブロックなどで行追加していけば済むものを、メタボックスで入力・削除・追加をするこどて本文をいちいち触らなくてもいいというメリットはあるように思うけど、個人的には別に使わなくてもいいんじゃない?という印象でした。
以下はCreating a “repeater meta-box” without a Plugin in WordPressのコードを参考に、更新履歴として機能させることができるよう以下のように改変したものです。
- コードの体系は私が見やすいようにした
- 各所の名称などを変更した
- 日付は日付ピッカーを使って選択できるようにした
- ショートコードでリスト表示できるようにした
特に後々自身が利用するケースはないと思うので、関数名などそのままで載せておきますから、これを参考に自身で研究・改変してみてください。
本ページ掲載のコードを使用するときは
本ページで掲載しているコードは、以下に了承した上で使用ください
- コードは商用・非商用問わず自由に使っていただいて構いませんが、コード追加による不具合やトラブルが発生しても当方では一切責任を負いません
- コードは有効化しているテーマのfunctions.php、style.cssなどへ追加することで機能します。それらのファイルへの変更を行うことに不安のある方は使用しないでください
- コードは本ページの公開日時点で私の環境において動作したものです。WordPressバージョン他環境の違いによって動作しないことがあります
- コードは、セキュリティ、コードの正確さなどにおいて完全なものではありません。中には紹介するコードを簡略化するために省略している部分があるものもありますので、ご自身でコードを十分に検証し、必要な部分の編集を行った上で使用するようにしてください
- 掲載しているのは参考コードです。自身の環境に合わせるための編集はご自身で対応いただく必要があります(コメント欄等から質問いただいても基本回答は致しません)
- 掲載しているコードの転載を禁じます(SNSで紹介いただいたり、本ページへのリンクを張っていただくことは大歓迎です)
リピーター(繰り返し)フィールドを使って投稿の更新情報を表示させるようにするコード例
このままコピペで動作すると思いますが、自身で必ずコードチェック等行ってください(不具合が出ても一切質問には回答しませんし、不具合が起きても責任は負いません)。
メタボックスの追加・データの保存や削除を行う機能を追加するためのコード
/***** 更新情報のメタボックス *****/
/*** 投稿へメタボックスを追加 ***/
function ha_add_mod_history_meta_boxes() {
add_meta_box(
'ha-modified-history-meta',
__('更新履歴',''),
'ha_mod_history_metabox_callback',
'post',
'normal',
'high'
);
}
add_action('admin_init', 'ha_add_mod_history_meta_boxes', 2);
/*** 日付ピッカーの導入 ***/
function ha_date_picker_init(){
wp_enqueue_script( 'jquery-ui-datepicker' );
wp_enqueue_style( 'ha-jquery-ui-datepicker-style', '//ajax.googleapis.com/ajax/libs/jqueryui/1.8.1/themes/smoothness/jquery-ui.css', true);
}
add_action('admin_enqueue_scripts','ha_date_picker_init');
/*** メタボックスの内容と処理 ***/
function ha_mod_history_metabox_callback() {
global $post;
//取得したmetaデータを変数に格納
$ha_mod_history_dbdata = get_post_meta($post->ID, 'ha_mod_history_meta_data', true);
//nonceフィールドの追加
wp_nonce_field( 'ha_mod_history_meta_box_nonce', 'ha_mod_history_meta_box_nonce' );
//追加・削除処理のスクリプトを出力
$script = '';
$script .= "<script>";
$script .= "jQuery(document).ready(function( $ ){";
$script .= "$( '#add-row' ).on('click', function() {";
$script .= "var row = $( '.empty-row.screen-reader-text' ).clone(true);";
$script .= "row.removeClass( 'empty-row screen-reader-text' );";
$script .= "row.insertBefore( '#repeatable-fieldset-one tbody>tr:last' );";
$script .= "return false;";
$script .= "});";
$script .= "$( '.remove-row' ).on('click', function() {";
$script .= "$(this).parents('tr').remove();";
$script .= "return false;";
$script .= "});";
$script .= "});";
$script .= "</script>";
echo $script;
//日付ピッカースクリプトを出力
$date_script = '';
$date_script .= "<script>";
$date_script .= "jQuery(document).ready(function(){";
$date_script .= "jQuery('.ha-date-picker').datepicker({";
$date_script .= "dateFormat : 'yy年mm月dd日'";
$date_script .= "});";
$date_script .= "});";
$date_script .= "</script>";
echo $date_script;
//テーブルの開始タグ
$table_start = '';
$table_start .= '<table id="repeatable-fieldset-one" width="100%">';
$table_start .= '<tbody>';
echo $table_start;
/*** 既存データの表示、または初期の新規入力項目の表示 ***/
if ( $ha_mod_history_dbdata ){//データベースにデータがあるか
foreach ( $ha_mod_history_dbdata as $field ) {//データ分だけ繰り返す
$tr_tag = '<tr style="background:#eee;">';
echo $tr_tag;
//日付入力項目の出力
$field01_value = $field['ModdateItem'];
if(isset( $field01_value )){
$field01 = $field01_value;
}else{
$field01 = '';
}
$field_html01 = '';
$field_html01 .= '<td style="width:15%;vertical-align:top;padding-top:8px;">';
$field_html01 .= '<input type="text" name="ModdateItem[]" class="ha-date-picker" value="'.$field01.'" />';
$field_html01 .= '</td> ';
echo $field_html01;
//説明文入力項目の出力
$field02_value = $field['ModDescription'];
if(isset( $field02_value )){
$field02 = $field02_value;
}else{
$field02 = '';
}
$field_html02 = '';
$field_html02 .= '<td style="width:70%;vertical-align:top;padding-top:8px;">';
$field_html02 .= '<textarea placeholder="内容" name="ModDescription[]" style="width:100%;">';
$field_html02 .= $field02;
$field_html02 .= '</textarea>';
$field_html02 .= '</td>';
echo $field_html02;
//削除ボタン
$field_html03 = '';
$field_html03 .= '<td style="width:15%;vertical-align:center;padding-top:8px;">';
$field_html03 .= '<a class="button remove-row" href="#1">データを削除</a>';
$field_html03 .= '</td>';
$field_html03 .= '';
echo $field_html03;
$tr_close_tag = '</tr>';
echo $tr_close_tag;
}//繰り返しの終了
}else{//データベースにデータがない場合
$blank_tr = '<tr style="background:#eee;">';
echo $blank_tr;
//日付入力項目の出力
$blank01_html = '';
$blank01_html .= '<td style="width:15%;vertical-align:top;padding-top:8px;"> ';
$blank01_html .= '<input type="text" name="ModdateItem[]" class="ha-date-picker" />';
$blank01_html .= '</td>';
echo $blank01_html;
//説明文入力項目の出力
$blank02_html = '';
$blank02_html .= '<td style="width:70%;vertical-align:top;padding-top:8px;">';
$blank02_html .= '<textarea placeholder="内容" name="ModDescription[]" style="width:100%;"></textarea>';
$blank02_html .= '</td>';
echo $blank02_html;
//削除ボタン
$blank03_html = '';
$blank03_html .= '<td style="width:15%;vertical-align:center;padding-top:8px;">';
$blank03_html .= '<a class="button cmb-remove-row-button button-disabled" href="#">データを削除</a>';
$blank03_html .= '</td>';
echo $blank03_html;
$blank_tr_close_tag = '</tr>';
echo $blank_tr_close_tag;
}
/*** 追加ボタンクリック時の行表示 ***/
$add_tr ='<tr class="empty-row screen-reader-text" style="background:#eee;">';
echo $add_tr;
//日付入力項目の出力
$add01_html = '<td style="width:15%;vertical-align:top;padding-top:8px;"> ';
$add01_html .= '<input type="text" name="ModdateItem[]" class="ha-date-picker" />';
$add01_html .= '<span style="font-size:0.7rem;">選択した日付は保存後画面をリロードすると表示されます</span>';
$add01_html .= '</td>';
echo $add01_html;
//説明文入力項目の出力
$add02_html = '';
$add02_html .= '<td style="width:70%;vertical-align:top;padding-top:8px;">';
$add02_html .= '<textarea placeholder="内容" name="ModDescription[]" style="width:100%;"></textarea>';
$add02_html .= '</td>';
echo $add02_html;
//削除ボタン
$add03_html = '';
$add03_html .= '<td style="width:15%;vertical-align:center;padding-top:8px;">';
$add03_html .= '<a class="button remove-row" href="#">データを削除</a>';
$add03_html .= '</td>';
echo $add03_html;
$add_close_tr = '</tr>';
echo $add_close_tr;
//テーブルの終了タグ
$table_end = '</tbody></table>';
echo $table_end;
//追加ボタンの出力
$add_btn = '<p><a id="add-row" class="button" href="#">データを追加</a></p>';
echo $add_btn;
}
/*** データの保存と削除 ***/
function ha_mod_history_metabox_save($post_id) {
//nonceチェックに失敗したら終了
if (!isset( $_POST['ha_mod_history_meta_box_nonce'] ) || !wp_verify_nonce($_POST['ha_mod_history_meta_box_nonce'], 'ha_mod_history_meta_box_nonce' ) ){
return;
}
//自動保存では処理しない
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE){
return;
}
//投稿の編集権限のないユーザーでは処理しない
if (!current_user_can('edit_post', $post_id)){
return;
}
$old = get_post_meta($post_id, 'ha_mod_history_meta_data', true);
$new = array();
$title = $_POST['ModdateItem'];
$description = $_POST['ModDescription'];
$count = count( $title );
for ( $i = 0; $i < $count; $i++ ) {
if ( $title[$i] != '' ){
$new[$i]['ModdateItem'] = stripslashes( strip_tags( $title[$i] ) );
$new[$i]['ModDescription'] = stripslashes( $description[$i] );
}
}
if ( !empty( $new ) && $new != $old ){
update_post_meta( $post_id, 'ha_mod_history_meta_data', $new );
}elseif ( empty($new) && $old ){
delete_post_meta( $post_id, 'ha_mod_history_meta_data', $old );
}
}
add_action('save_post', 'ha_mod_history_metabox_save');
データをショートコードで呼び出すためのコード
/*** ショートコードでリピーターフィールドの内容をリスト表示 ***/
function pwcn_repeat_field_sc_test(){
$meta_data_all = get_post_meta( get_the_ID(), 'ha_mod_history_meta_data', true );
ob_start();
echo '<ul>';
foreach( $meta_data_all as $meta_data){
echo '<li>'.esc_html($meta_data['ModdateItem']).' / '.esc_html($meta_data['ModDescription']).'</li>';
}
echo '</ul>';
return ob_get_clean();
}
add_shortcode('pwcn-r-field','pwcn_repeat_field_sc_test');
後述
作ってみて分かったのは、Custom Field Suiteというプラグインがリピーターフィールドに限らず、GUI(管理画面)状でフィールドの設定や種類の選択を自由にしたものをメタボックスとして表示し、きちんとデータの入力更新ができるようになっていること。
とりわけリピーターフィールドとなると、上記コードのように「日付」と「内容」の2つの項目だけを作るのにも結構な量のコードが必要になるのに、このプラグイン1つで簡単にできてしまうのには驚きしかありません。
現在私は必要であれば自身でこれらの制御を行うコードを書いて運営しているので、特にこのプラグインを使用している(使用していた)わけではありませんが、利用者の方は感謝こそすれ、公開が停止されたことについて悪態をつくことは厳に慎むべきだと思います。
文句言うなら自身でこうしてコード書いてみればいいわけですからね。
コメントを残す