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にてACFで設定したカスタムフィールドの値を元に記事を並べ替える方法
WordPressにてAdvanced Custom Fieldsで設定したカス ...
-
Advanced Custom Fieldsでチェックボックスの記事を取得
Advanced Custom Fieldsでチェックボックス設定しているカスタ ...
-
WordPressで記事毎に設定したバナー広告を表示させる方法
WordPressでGoogleアドセンスのようなクリック広告ではなく、商品を指 ...
-
WordPressでカスタムフィールドとCSVファイル投稿する方法
WordPressでカスタムフィールド設定している環境に、CSVファイルアップロ ...
-
WordPressにてAdvanced Custom Fieldsを用いて連載(シリーズ)記事機能を実装する方法
先日「Series」プラグインで連載(シリーズ)記事機能の実装方法をメモしたが、 ...