この実装、面倒なら代行します
固定ページや投稿、カスタム投稿タイプなどにカスタムフィールドを持たせることがよくあります。
入力の手間が省け、htmlの知識がない人でも簡単に高機能なWebレイアウトを作ることができとても便利です。
ところが、カスタムフィールド管理のプラグインでCustom Field Suiteを使うと、「プレビュー」(「更新」せずに表示を確認できる機能)ができない、という問題があります。
そこで今回は、Custom Field Suiteを使ったカスタムフィールドを持つページの「プレビュー」を表示する方法のご紹介。
まずプラグインを作り、有効にします。
(作り方の基礎が知りたければWordPressのプラグインを作成する(初級)を参考にしてください。)
<?php /* Plugin Name: Custom field suite preview bug fix Author: kaiza Plugin URI: Description: Custom field suite preview bug fix Version: 0.1.0 Author URI: */ $cfs_fix = new Custom_Field_Suite_Preview(); class Custom_Field_Suite_Preview { function __construct(){ add_action('plugins_loaded', array($this, 'plugins_loaded')); } public function plugins_loaded(){ add_action('cfs_init', array($this, 'cfs_init'), 0); add_action('wp_insert_post', array($this, 'wp_insert_post')); add_filter('get_post_metadata', array($this, 'get_post_metadata'), 10, 4 ); add_shortcode('cfs_get', function($p){ extract(shortcode_atts(array( 'key' => false, 'id' => 0, 'format' => array(), ), $p)); return self::get($key, $id, $format); }); } public function get($key, $id = 0, $format = array()){ global $cfs; if (intval($this->get_preview_id($id))) { return $cfs->get($key, $this->get_preview_id($id), $format); } elseif ($id = $this->get_preview_id(get_the_ID())) { return $cfs->get($key, $id, $format); } else { return $cfs->get($key, get_the_ID(), $format); } } public function cfs_init(){ if (isset($_POST['wp-preview']) && $_POST['wp-preview'] === 'dopreview') { global $cfs; remove_action('cfs_init', array($cfs->form, 'init')); } } public function get_preview_id( $post_id ){ global $post; $preview_id = 0; if (isset($post->ID) && intval($post->ID) === intval($post_id) && is_preview() && $preview = wp_get_post_autosave($post->ID)) { $preview_id = $preview->ID; } return $preview_id; } public function get_post_metadata( $return, $post_id, $meta_key, $single ) { if ($preview_id = $this->get_preview_id($post_id)) { if ($post_id !== $preview_id) { $return = get_post_meta($preview_id, $meta_key, $single); } } return $return; } public function wp_insert_post($post_ID){ if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return; } if (defined('DOING_AJAX') && DOING_AJAX) { return; } if (wp_is_post_revision($post_ID)) { global $wpdb; global $cfs; $wpdb->query($wpdb->prepare( "DELETE FROM $wpdb->postmeta WHERE post_id = %d", $post_ID )); $cfs->form->session = new cfs_session(); $session = $cfs->form->session->get(); $field_groups = array(); if (isset($session['field_groups'])) { $field_groups = $session['field_groups']; } foreach ($field_groups as $key => $val) { $field_groups[$key] = (int) $val; } $options = array( 'format' => 'input', 'field_groups' => $field_groups ); //ユーザーさんからいただいた改善案にもとづき、修正しています。 if(!empty($_POST['cfs']['input'])) { $cfs->save($_POST['cfs']['input'], array('ID' => $post_ID), $options); } //元のコード $cfs->save($_POST['cfs']['input'], array('ID' => $post_ID), $options); $post_metas = array('meta'); foreach ( $post_metas as $post_meta ) { foreach ( $_POST[$post_meta] as $meta_id => $meta_arr ) { add_metadata('post', $post_ID, $meta_arr['key'], $meta_arr['value']); } } } } }
これで、「プレビュー」が押されたときに、Custom Field Suiteで作ったカスタムフィールドの値を自動セーブします。
今度は表示側(page.phpなど)です。
自動セーブされた値を取得するために、Custom Field Suiteの関数は使わず、WordPress標準のget_post_meta関数を使ってカスタムフィールドを読み込むようにします。
<? php //画像の読み込み $image1 = get_post_meta($post->ID, 'image1', true); $image1 = content_url().'/uploads/'.get_post_meta($image1, '_wp_attached_file', true); //テキストの読み込み $text1 = get_post_meta($post->ID, 'text1', true); //繰り返しフィールドの読み込み $repeat1_fields = get_post_meta($post->ID, 'repeat1', false); $count_total = count($repeat1_fields ); $count_total = $count_total/2; //同じ値が2つ登録されるので1つだけ取り出すための調整式 $repeat_fields = array(); for($i = 0; $i < $count_total; $i++){ $repeat_fields[$i]['repeat1']=$repeat1_fields[$i]; } //ユーザーさんからいただいた改善案では、次のような書き方もでき、 //これだと即時の更新ができるそうです。 if(is_preview()) { $id = get_preview_id(get_the_ID()); } else { $id = $post->ID; } $program_cfs = CFS()->get(false,$id); $image1 = $program_cfs['image1']; $text1 = $program_cfs['text1']; //ただし、繰り返しフィールドの読み込みがこれでできるのか調べていないので、一応、当方のコードも上述のまま残しておきます。 ?> テキスト表示 <?php echo $text1; ?> 画像表示 <img src="<?php echo $image1; ?>" > 繰り返しフィールドの表示 foreach ($repeat_fields as $repeat_field) { echo $repeat_field['repeat1'].'<br>'; }
これでプレビュー表示されます。
※ ただし、これをしても、2回に1回しか変更した内容が反映されたページは表示されません。
2回に1回は変更前の“今公開されているページ”がプレビューとして現れます。
なぜそうなるかまでは突き止められませんでした。
ちなみに私たちが普段使っているカスタムフィールド管理用プラグイン Advanced Custom Fieldsでも同じ現象が起きます。。
あしからず。
WordPressカスタマイズ事例やウェブ制作ノウハウの新着情報、お役立ち情報を
リアルタイムにメルマガ配信!
100ウェブで手がけた制作・開発案件を一部、ご紹介。
クライアントからご相談いただいた内容とその実装におけるポイント、工期、予算について確認いただけます。
【テレワーク実施中 につきお電話転送中】
コール中1秒程度無音状態になりますがそのままお待ちください。
受付時間
平日 10:00~18:00
メールでのお問い合わせでも
1営業日以内にご連絡いたします。