24歳、習作です。
MW WP Formを使って記事タイトルのようなことをやりたかったのですが、ググってもそれっぽい記事がなかったので自分で組んでみました。
概要
要するにこういうやつです。
それぞれの項目はカスタム投稿で管理し、希望コース名は投稿タイトル、希望日時はカスタムフィールドで入力するとします。
なお、カスタムフィールドは自由に項目数を増減できるようにWPAlchemyのRepeating Field Groupsを使用しています。
参考:WPAlchemy MetaBox PHP Class#Repeating Field Groups
※Advanced Custom FieldsのRepeater Fieldアドオンでもできると思います
大まかな流れ
希望コースのプルダウンを変更する
↓
変更後の値を取得し、AjaxでAPIにリクエストして希望日時の一覧を取得する
↓
取得した希望日時の一覧をjQueryでプルダウンにセットする
前提条件
- カスタム投稿名
- course
- カスタムフィールドグループ名
- variable_date
- 希望日時のカスタムフィールド名
- date
コード
<dl>
<dt><label for="course">希望コース</label></dt>
<dd>[mwform_select name="course_name" id="course"]</dd>
<dt><label for="date">希望日時</label></dt>
<dd>[mwform_select name="course_date" id="date"]</dd>
</dl>
通常通り、MW WP Formの記法でプルダウンの項目を作成します。
なお、プルダウンの値はフィルターフックを使って挿入するのでフォーム側のコードでは入力しません。
/**
* フォームのプルダウンの値を出力する
* @param array $children select配下のoption値
* @return array $atts フォームの要素
*/
function set_select_children($children, $atts){
// カスタム投稿名courseの投稿を全て取得し、各投稿のタイトルを希望コースのプルダウンの値として挿入する
if($atts['name'] == 'course_name'){
$args = array(
'post_type' => 'course',
'posts_per_page' => -1,
'post_status' => 'publish'
);
$posts = get_posts($args);
foreach($posts as $post){
$children[$post->post_title] = $post->post_title;
}
}
// カスタム投稿名courseの投稿を全て取得し、かつ各投稿のカスタムフィールドを全て取得した上で
// 希望日時のプルダウンの値として挿入する
elseif($atts['name'] == 'course_date'){
$args = array(
'post_type' => 'course',
'posts_per_page' => -1,
'post_status' => 'publish'
);
$posts = get_posts($args);
foreach($posts as $post){
$dates = get_post_meta($post->ID, 'variable_date', true);
foreach($dates as $date){
$children[$date['date']] = $date['date'];
}
}
}
return $children;
}
add_filter('mwform_choices_mw-wp-form-xxx', 'set_select_children', 10, 2);
functions.phpに、MW WP Formのmwform_choices_mw-wp-formのフィルターフックを使用して各プルダウンに値をセットする関数を記載します。
参考:mwform_choices_mw-wp-form-xxx | MW WP Form
require_once('../../../wp-load.php');
$args = array(
'post_type' => 'course',
'posts_per_page' => -1,
'post_status' => 'publish',
's' => $_POST['course'],
'exact' => true
);
$post = reset(get_posts($args));
$dates = get_post_meta($post->ID, 'variable_date', true);
foreach($dates as $date){
$return_data[] = $date['date'];
}
$return_data = json_encode($return_data);
echo $return_data;
テーマフォルダ直下にAjax用のAPIを作成します。
postされた値をカスタム投稿名courseの投稿一覧から検索し、該当する投稿のカスタムフィールドから値を取得して配列に格納し、JSON形式で値を返します。
※このへんはWordPressのREST APIを使用すればわざわざファイルを作る必要はないかもしれません
(function($){
$(function(){
set_date_value();
$('#course').change(function(){
set_date_value();
});
});
function set_date_value(){
$.ajax({
url: '/wp-content/themes/theme_name/api.php',
type: 'post',
dataType: 'json',
data: {
course: $('#course').val()
}
})
.done(function(response){
var date = $('#date').val(),
selected_val = null;
$('#date').children().remove();
$.each(response, function(index, value){
$('#date').append($("<option>").val(value).text(value));
if(value == date){
selected_val = value;
}
});
if(selected_val == null){
selected_val = $('#date option:eq(0)').val();
}
$('#date').val(selected_val);
})
.fail(function(){
alert('エラーが発生しました。');
});
}
})(jQuery);
フォームのページで読み込むJavaScriptファイルです。
テーマフォルダ直下のapi.phpにAjaxを使用してpostを行い、値が返ってきたら希望日時のプルダウンの中身を空にした上で返ってきた値をセットします。
終わりに
かなり場当たり的なコードなので正直スマートなやり方ではないなあと自分でも思うのですが、参考までに。
バリデーションやプルダウンの最初の項目を「選択してください」的なものにすることはあまり考慮していませんが、そちらは別途検証したいと思います。