WordPressカスタムフィールド:Smart Custom Fields代替とadd_meta_box
何度かこのブログでも、書いていますが、リピーターを使えるカスタムフィールドプラグインが有料しかなく、頼りだった「Custom Field Suite」の脆弱性発見による公開停止に追い打ちをかけられて、またプラグインを探す旅にでておりました。
でも、探せども見つからずたどり着いたのはfunctionへの直がき。
参考にしたのは下記のGitHubです。
バナー登録のリピーター
ひとまず作ってみたのが、バナー画像、バナータイトル、バナーURLの3つのフィールドを固定ページ1877に追加するリピーターです。
functionに追記しました。
- 条件のフック名:ha_add_top_banners_meta_boxes
- フック名:top_banners_meta_box_display
- リピーターのグループ名:top_banners
- バナー画像:top_banner_img
- バナータイトル:top_banner_name
- バナーURL:top_banner_url
<?php
add_action('admin_init', 'ha_add_top_banners_meta_boxes', 2);
function ha_add_top_banners_meta_boxes() {
// 固定ページIDが1877である場合のみメタボックスを追加
$post_id = isset($_GET['post']) ? $_GET['post'] : (isset($_POST['post_ID']) ? $_POST['post_ID'] : '');
if ($post_id == 1877) {
add_meta_box('top_banners_group', 'トップバナー', 'top_banners_meta_box_display', 'page', 'normal', 'default');
}
}
function top_banners_meta_box_display() {
global $post;
$top_banners = get_post_meta($post->ID, 'top_banners', true);
wp_nonce_field('top_banners_meta_box_nonce', 'top_banners_meta_box_nonce');
?>
<script type="text/javascript">
jQuery(document).ready(function($) {
$('#add-row').on('click', function() {
var row = $('.empty-row.screen-reader-text').clone(true);
row.removeClass('empty-row screen-reader-text');
row.find('input, textarea').val(''); // フィールドをクリア
row.insertBefore('#repeatable-fieldset-one tbody>tr:last');
return false;
});
$(document).on('click', '.remove-row', function() {
$(this).parents('tr').remove();
return false;
});
});
</script>
<table id="repeatable-fieldset-one" width="100%">
<tbody>
<?php
if ($top_banners) {
foreach ($top_banners as $field) {
?>
<tr>
<td><input type="text" name="top_banner_name[]" placeholder="サイト名" value="<?php echo esc_attr($field['top_banner_name']); ?>" /></td>
<td>
<input type="hidden" name="top_banner_img[]" value="<?php echo esc_attr($field['top_banner_img']); ?>" />
<button class="upload_image_button button">画像を選択</button>
<img src="<?php echo esc_url($field['top_banner_img']); ?>" style="max-width: 150px; display: <?php echo $field['top_banner_img'] ? 'block' : 'none'; ?>" />
</td>
<td><input type="text" name="top_banner_url[]" placeholder="サイトURL" value="<?php echo esc_attr($field['top_banner_url']); ?>" /></td>
<td><textarea name="top_banner_txt[]" placeholder="説明文 (50文字以内)" maxlength="50"><?php echo esc_textarea($field['top_banner_txt']); ?></textarea></td>
<td><a class="button remove-row" href="#">削除</a></td>
</tr>
<?php
}
} else {
// 空のテンプレート行
?>
<tr>
<td><input type="text" name="top_banner_name[]" placeholder="サイト名" /></td>
<td>
<input type="hidden" name="top_banner_img[]" />
<button class="upload_image_button button">画像を選択</button>
<img src="" style="max-width: 150px; display: none;" />
</td>
<td><input type="text" name="top_banner_url[]" placeholder="サイトURL" /></td>
<td><textarea name="top_banner_txt[]" placeholder="説明文 (50文字以内)" maxlength="50"></textarea></td>
<td><a class="button remove-row" href="#">削除</a></td>
</tr>
<?php
}
?>
<tr class="empty-row screen-reader-text">
<td><input type="text" name="top_banner_name[]" placeholder="サイト名" /></td>
<td>
<input type="hidden" name="top_banner_img[]" />
<button class="upload_image_button button">画像を選択</button>
<img src="" style="max-width: 150px; display: none;" />
</td>
<td><input type="text" name="top_banner_url[]" placeholder="サイトURL" /></td>
<td><textarea name="top_banner_txt[]" placeholder="説明文 (50文字以内)" maxlength="50"></textarea></td>
<td><a class="button remove-row" href="#">削除</a></td>
</tr>
</tbody>
</table>
<p><a id="add-row" class="button" href="#">フィールドを追加</a></p>
<?php
}
add_action('save_post', 'top_banners_meta_box_save');
function top_banners_meta_box_save($post_id) {
// 固定ページIDが1877でない場合は保存しない
if ($post_id != 1877) {
return;
}
if (!isset($_POST['top_banners_meta_box_nonce']) ||
!wp_verify_nonce($_POST['top_banners_meta_box_nonce'], 'top_banners_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, 'top_banners', true);
$new = array();
$names = $_POST['top_banner_name'];
$urls = $_POST['top_banner_url'];
$imgs = $_POST['top_banner_img'];
$texts = $_POST['top_banner_txt'];
$count = count($names);
for ($i = 0; $i < $count; $i++) {
if ($names[$i] != '') {
$new[$i]['top_banner_name'] = sanitize_text_field($names[$i]);
$new[$i]['top_banner_url'] = esc_url_raw($urls[$i]);
$new[$i]['top_banner_img'] = esc_url_raw($imgs[$i]);
$new[$i]['top_banner_txt'] = sanitize_textarea_field($texts[$i]);
}
}
if (!empty($new) && $new != $old) {
update_post_meta($post_id, 'top_banners', $new);
} elseif (empty($new) && $old) {
delete_post_meta($post_id, 'top_banners', $old);
}
}
function ha_enqueue_media_uploader() {
wp_enqueue_media();
?>
<script>
jQuery(document).ready(function($) {
function initImageUploader() {
$('.upload_image_button').off('click').on('click', function(e) {
e.preventDefault();
var button = $(this);
var custom_uploader = wp.media({
title: '画像を選択',
button: { text: '画像を選択' },
multiple: false
}).on('select', function() {
var attachment = custom_uploader.state().get('selection').first().toJSON();
button.prev('input').val(attachment.url);
button.next('img').attr('src', attachment.url).show();
}).open();
});
}
initImageUploader(); // 初期化
// 行追加時に再初期化
$('#add-row').on('click', function() {
setTimeout(initImageUploader, 500); // 新しい行に対応
});
});
</script>
<?php
}
add_action('admin_footer', 'ha_enqueue_media_uploader');
?>
リピーターの呼び出し
<ul class="listProject row">
<?php $top_banners = get_post_meta(get_the_ID(), 'top_banners', true);
if (!empty($top_banners)) {
foreach ($top_banners as $banner) {
?>
<li class="col-md-3 col-6 inview_fadeIn">
<div class="cardItem">
<a href="<?php echo esc_url($banner['top_banner_url']); ?>" target="_blank">
<figure class="thumb"><img src="<?php echo esc_url($banner['top_banner_img']); ?>" alt="<?php echo esc_attr($banner['top_banner_name']); ?>" /></figure>
</a>
<p class="detail"><?php echo esc_html($banner['top_banner_txt']); ?></p>
<?php /*<a class="viewMore" href="<?php echo $fields['banner_link']; ?>" target="_blank">
<span class="text">Webサイトへ</span>
<div class="blank"></div>
</a> */ ?>
</div>
</li>
<?php }
} ?>
</ul>
add_meta_boxへの挑戦
私自身、ずっとカスタムフィールドはプラグインに頼っていたため、初の試みで不安はあるものの、WordPress 6.6.2での稼働は確認しています。通常のカスタムフィールドもadd_meta_box作成で対応可能でした。
一旦、作れれば応用できそうなので、様子を見ながら使用していこうかと思っています。
カスタムフィールドプラグインの便利さが身に沁みます。むしろ、有料化にも納得できました。
関連記事