Advanced Custom Fieldsでセレクトメニューを動的に生成する方法
2024/02/20
WordPressでカスタムフィールド設定用のプラグインAdvanced Custom Fieldsを使用中の環境で、記事投稿ページからセレクトメニューを選択すると、選択したものと連動したセレクトメニューが次に表示されるというシステムが欲しかった。以下に方法をメモ。
やりたいこと
八地方区分(関東、近畿等)をプルダウンから選ぶと区分内の都道府県プルダウンが表示され、さらに都道府県を選ぶと路線が、路線を選ぶと駅名が選択できるといった一連のセレクトメニューをWordPressの記事一覧ページに作成したかった。
都道府県等のデータ用意やセレクトメニュー自体の作成方法は以下記事を参照。
ACF側の設定
以下のような形で設定しておく。
| フィールドラベル | フィールド名 | フィールドタイプ | 選択肢 |
| 八地方区分 | region | セレクトメニュー | 1 : 北海道 2 : 東北地方 3 : 関東地方 4 : 中部地方 5 : 近畿地方 6 : 中国地方 7 : 四国地方 8 : 九州地方 |
| 都道府県 | prefecture | セレクトメニュー | 空でOK |
| 路線種別 | line | ラジオボタン | 0 : 地下鉄 1 : 私鉄 2 : JR |
| 地下鉄 | subway | セレクトメニュー | 空でOK |
| 私鉄 | private | セレクトメニュー | 空でOK |
| JR | jr | セレクトメニュー | 空でOK |
| 駅 | station | セレクトメニュー | 空でOK |
functions.phpに追記
#js呼び出し
function search_station_js($hook) {
if($hook == 'post.php' || $hook == 'post-new.php'){
#JSファイル設置場所
wp_enqueue_script('custom_admin_script', '/hogehoge/js/search_station.js', array('jquery'));
}
}
add_action('admin_enqueue_scripts', 'search_station_js');
#ajax受信用
function search_station(){
#DB接続
global $wpdb;
$mysqli = new mysqli($wpdb->dbhost, $wpdb->dbuser, $wpdb->dbpassword, $wpdb->dbname);
$mysqli->set_charset('utf8');
$mode = $_POST['mode'];
$result = false;
#エリア選択
if( $mode == 'region' && $_POST['id'] ){
$sql = '
SELECT *
FROM cps_prefecture
WHERE region_id = "' . $mysqli->real_escape_string($_POST['id']) . '"
';
$row = $mysqli->query($sql);
while ($rs = $row->fetch_array(MYSQLI_ASSOC)) {
$result[] = $rs;
}
#都道府県選択
}else if( $mode == 'prefecture' && $_POST['id'] ){
$sql = '
SELECT
c.company_cd, c.company_name, c.company_name_r, c.company_type, c.subway,
l.line_name, l.line_cd,
s.pref_cd
FROM cps_company AS c
LEFT JOIN cps_line AS l
ON c.company_cd = l.company_cd
LEFT JOIN cps_station AS s
ON l.line_cd = s.line_cd
WHERE s.e_status = 0
AND l.e_status = 0
AND s.e_status = 0
AND s.pref_cd = "' . $mysqli->real_escape_string($_POST['id']) . '"
GROUP BY l.line_cd
';
$row = $mysqli->query($sql);
while ($rs = $row->fetch_array(MYSQLI_ASSOC)) {
$result[] = $rs;
}
#路線選択
}else if( $mode == 'station' && $_POST['id'] ){
$sql = '
SELECT *
FROM cps_station
WHERE line_cd = "' . $mysqli->real_escape_string($_POST['id']) . '"
AND e_status = 0
';
$row = $mysqli->query($sql);
while ($rs = $row->fetch_array(MYSQLI_ASSOC)) {
$result[] = $rs;
}
}
#結果がある場合は返す
if( $result ){
echo json_encode($result);
}
die();
}
add_action( 'wp_ajax_select_station', 'search_station' );
wp-config.phpで設定されているMySQLのログイン情報が定数だったのでそのまま「DB_PASSWORD」とかで取得しようとしたらエラーが起きた。以下で取得できるというのを初めて知った。
global $wpdb; $mysqli = new mysqli($wpdb->dbhost, $wpdb->dbuser, $wpdb->dbpassword, $wpdb->dbname);
JavaScript
今回だと「/hogehoge/js/search_station.js」のファイルを以下内容でアップロードする。
//ACF設定画面のKeyをここに書く
var region_id = 'acf-field_xxxxxxxxxxxxxx';
var prefecture_id = 'acf-field_xxxxxxxxxxxxxx';
var subway_id = 'acf-field_xxxxxxxxxxxxxx';
var private_id = 'acf-field_xxxxxxxxxxxxxx';
var jr_id = 'acf-field_xxxxxxxxxxxxxx';
var station_id = 'acf-field_xxxxxxxxxxxxxx';
(function($) {
$(document).ready(function(){
$(document).on( 'change blur', `#${region_id}, #${prefecture_id}, #${subway_id}, #${private_id}, #${jr_id}`, function(){
var selecter_id = $(this).attr("id");
//エリア選択
if( selecter_id == region_id ){
var mode = 'region';
//都道府県選択
}else if( selecter_id == prefecture_id ){
var mode = 'prefecture';
//路線選択
}else{
var mode = 'station';
}
$.ajax({
type: 'POST',
url: ajaxurl,
data: {
'action' : 'select_station',
'id' : $(this).val(),
'mode' : mode
},
success: function( result ){
//エリア選択
if( selecter_id == region_id ){
var prefecture = $.parseJSON(result);
var html = '';
for(var key in prefecture){
html += '<option value="' + prefecture[key]['id'] + '">' + prefecture[key]['name'] + '</option>';
}
$('#' + prefecture_id).html(html);
//都道府県選択
}else if( selecter_id == prefecture_id ){
var line = $.parseJSON(result);
var subway = '';
var private = '';
var jr = '';
for(var key in line){
if( line[key]['subway'] == 1 ){
subway += '<option value="' + line[key]['line_cd'] + '">' + line[key]['line_name'] + '</option>';
}else if( line[key]['company_type'] == 1 ){
jr += '<option value="' + line[key]['line_cd'] + '">' + line[key]['line_name'] + '</option>';
}else{
private += '<option value="' + line[key]['line_cd'] + '">' + line[key]['line_name'] + '</option>';
}
}
$('#' + subway_id).html(subway);
$('#' + private_id).html(private);
$('#' + jr_id).html(jr);
//路線選択
}else{
var station = $.parseJSON(result);
var html = '';
for(var key in station){
html += '<option value="' + station[key]['station_cd'] + '">' + station[key]['station_name'] + '</option>';
}
$('#' + station_id).html(html);
}
}
});
return false;
});
});
})(jQuery);
WordPressでajax通信をする際はajaxurl(/wp-admin/admin-ajax.php)にリクエストしないといけないらしい。最初適当なディレクトリに突っ込んで呼び出そうとしたがエラーが起きた。
あとACFを使っているとjQuery等で各カスタムフィールドが後から追加されるので、4行目の部分は以下の通り注意する。
#後から追加される要素はこれだと動かない
$('セレクタ').change(function()){
#これだと動く
$(document).on( 'change blur', `セレクタ`, function(){
関連記事
-
-
WordPressでカスタムフィールドとCSVファイル投稿する方法
WordPressでカスタムフィールド設定している環境に、CSVファイルアップロ ...
-
-
Advanced Custom FieldsでGoogleMapの使用する方法
Advanced Custom FieldsでGoogleMapを使用したかった ...
-
-
Advanced Custom Fieldsで設定した項目を条件に記事一覧を取得する方法
WordPressでAdvanced Custom Fieldsにて設定した項目 ...
-
-
WordPressにてACFで設定したカスタムフィールドの値を元に記事を並べ替える方法
WordPressにてAdvanced Custom Fieldsで設定したカス ...
-
-
WordPressで記事毎に設定したバナー広告を表示させる方法
WordPressでGoogleアドセンスのようなクリック広告ではなく、商品を指 ...