カスタムフィールドで画像の保存時に他の画像が使えない
-
現在、WordPressを用いてカフェのホームページを作っています。
カスタムフィールドの機能が非常に便利なので使っています。今回、TOPページのスライドショーに用いる画像とその説明文をカスタムフィールドにて登録し、front-page.php内で呼び出すことで管理者が後からスライドショーの画像と説明文を変更できるようにしようと考えています。
WordPressのTOPページの設定は、TOPページ用の固定ページを作成し、そのページのテンプレートとしてfront-page.phpを使用しています。
また、その固定ページを設定用のページとして、TOPページに実際に表示するHTMLなどは直接front-page.php内に記述し、固定ページはカスタムフィールドを入力するためのページとして使用します。こちらの記事やカスタムフィールドの作成、入力、保存に関する各関数のCODEXを参考に以下のソースコードをテーマ内のfunction.phpに記載しましたが、保存時に意図しない挙動があり、その原因を突き止めたいです。
// カスタムフィールド ボックスを追加 function add_my_cf($post) { $post_id = $post->ID; if($post_id == get_option('page_on_front')) { add_meta_box( 'basic_info', '基本情報', 'insert_basic_info_cf', 'page', 'normal', 'high'); add_meta_box('slideshow_img', 'スライドショーで使う画像', 'insert_slideshow_img_cf', 'page', 'normal', 'high'); } } add_action('add_meta_boxes_page', 'add_my_cf', 10, 2); function custom_metabox_edit_form_tag(){ echo ' enctype="multipart/form-data"'; } //画像をアップする場合は、multipart/form-dataの設定が必要なので、post_edit_form_tagをフックしてformタグに追加 add_action('post_edit_form_tag', 'custom_metabox_edit_form_tag'); // カスタムフィールド:基本情報 の入力エリア function insert_basic_info_cf() { global $post; // nonceフィールドを追加して後でチェックする wp_nonce_field( 'save_my_cf', 'basic_info_cf_nonce' ); echo '電話番号: <input type="text" name="basic_info_phone" id="basic_info_phone" value="'.get_post_meta($post->ID, 'basic_info_phone', true).'" size="50" /><br>'; echo 'メールアドレス: <input type="text" name="basic_info_email" id="basic_info_email" value="'.get_post_meta($post->ID, 'basic_info_email', true).'" size="50" /><br>'; echo '郵便番号: <input type="text" name="basic_info_postalcode" id="basic_info_postalcode" value="'.get_post_meta($post->ID, 'basic_info_postalcode', true).'" size="50" /><br>'; echo '住所: <input type="text" name="basic_info_address" id="basic_info_address" value="'.get_post_meta($post->ID, 'basic_info_address', true).'" size="50" /><br>'; echo '定休日: <input type="text" name="basic_info_holiday" id="basic_info_holiday" value="'.get_post_meta($post->ID, 'basic_info_holiday', true).'" size="50" /><br>'; echo '開店時間: <input type="text" name="basic_info_open" id="basic_info_open" value="'.get_post_meta($post->ID, 'basic_info_open', true).'" size="50" /><br>'; echo '閉店時間: <input type="text" name="basic_info_close" id="basic_info_close" value="'.get_post_meta($post->ID, 'basic_info_close', true).'" size="50" /><br>'; echo '最終入店時間: <input type="text" name="basic_info_last_entering" id="basic_info_last_entering" value="'.get_post_meta($post->ID, 'basic_info_last_entering', true).'" size="50" /><br>'; } // カスタムフィールド:スライドショー画像の入力エリア function insert_slideshow_img_cf() { global $post; // nonceフィールドを追加して後でチェックする wp_nonce_field( 'save_my_cf', 'slideshow_img_cf_nonce' ); for($i = 1; $i <= 6; $i++) { echo '画像'.$i.'のファイル: <input type="file" name="slideshow_img'.$i.'_img" accept="image/*" /><br>'; if(!empty(get_post_meta($post->ID, 'slideshow_img'.$i.'_img', true)) && strlen(get_post_meta($post->ID, 'slideshow_img'.$i.'_img', true)) > 0){ //キーのpostmeta情報がある場合は、画像を表示 echo '<img style="width: 200px;display: block;margin: 1em;" src="'.wp_get_attachment_url(get_post_meta($post->ID, 'slideshow_img'.$i.'_img', true)).'">'; echo '<div>'.get_post_meta($post->ID, 'slideshow_img'.$i.'_img', true).'</div>'; } echo '画像'.$i.'の説明文(最大100文字): <input type="text" name="slideshow_img'.$i.'_desc" id="slideshow_img'.$i.'_desc" value="'.get_post_meta($post->ID, 'slideshow_img'.$i.'_desc', true).'" size="100" /><br>'; } } // カスタムフィールドの値を保存 function save_my_cf( $post_id ) { // nonceがセットされているかどうか確認 $cf_nonces = ['basic_info_cf_nonce','slideshow_img_cf_nonce']; foreach($cf_nonces as $cf_nonce) { if ( ! isset( $_POST[$cf_nonce] ) ) { return; } // nonceが正しいかどうか検証 if ( ! wp_verify_nonce( $_POST[$cf_nonce], 'save_my_cf' ) ) { return; } } // 自動保存の場合はなにもしない if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { return; } // ユーザー権限の確認 if ( isset( $_POST['post_type'] ) && 'page' == $_POST['post_type'] ) { if ( ! current_user_can( 'edit_page', $post_id ) ) { return; } } else { if ( ! current_user_can( 'edit_post', $post_id ) ) { return; } } /* 安全が確認できたのでデータを保存する */ // basic_info $basic_info_cf_keys = ['basic_info_phone', 'basic_info_email', 'basic_info_postalcode', 'basic_info_address', 'basic_info_holiday', 'basic_info_open', 'basic_info_close', 'basic_info_last_entering']; foreach($basic_info_cf_keys as $basic_info_cf_key) { if(!empty($_POST[$basic_info_cf_key])) { update_post_meta($post_id, $basic_info_cf_key, sanitize_text_field($_POST[$basic_info_cf_key])); } else { delete_post_meta($post_id, $basic_info_cf_key, get_post_meta($post_id, $basic_info_cf_key, true)); } } // slideshow_img // slideshow_img_img $slideshow_img_img_cf_keys = []; for($i = 1; $i <= 6; $i++) { $slideshow_img_img_cf_keys[] = 'slideshow_img'.$i.'_img'; } foreach($slideshow_img_img_cf_keys as $slideshow_img_img_cf_key) { if(!empty($_FILES[$slideshow_img_img_cf_key]) && $_FILES["slideshow_img".$i."_img"]["size"] !== 0){ $file_name = basename($_FILES[$slideshow_img_img_cf_key]['name']); $file_name = trim($file_name); $file_name = str_replace(" ", "-", $file_name); $wp_upload_dir = wp_upload_dir(); //現在のuploadディクレトリのパスとURLを入れた配列 $upload_file = $_FILES[$slideshow_img_img_cf_key]['tmp_name']; $upload_path = $wp_upload_dir['path'].'/'.$file_name; //uploadsディレクトリ以下などに配置する場合は$wp_upload_dir['basedir']を利用する //画像ファイルをuploadディクレトリに移動させる move_uploaded_file($upload_file,$upload_path); $file_type = $_FILES[$slideshow_img_img_cf_key]['type']; //正規表現で拡張子なしのスラッグ名を生成 $slug_name = preg_replace('/\.[^.]+$/', '', basename($upload_path)); if(file_exists($upload_path)){ //保存に成功してファイルが存在する場合は、wp_postsテーブルなどに情報を追加 $attachment = array( 'guid' => $wp_upload_dir['url'].'/'.basename($file_name), 'post_mime_type' => $file_type, 'post_title' => $slug_name, 'post_content' => '', 'post_status' => 'inherit' ); //添付ファイルを追加 $attach_id = wp_insert_attachment($attachment,$upload_path,$post_id); if(!function_exists('wp_generate_attachment_metadata')){ require_once(ABSPATH . "wp-admin" . '/includes/image.php'); } //添付ファイルのメタデータを生成し、wp_postsテーブルに情報を保存 $attach_data = wp_generate_attachment_metadata($attach_id,$upload_path); wp_update_attachment_metadata($attach_id,$attach_data); //wp_postmetaテーブルに画像のattachment_id(wp_postsテーブルのレコードのID)を保存 update_post_meta($post_id, $slideshow_img_img_cf_key,$attach_id); }else{ //保存失敗 echo '画像保存に失敗しました'; exit; } } } // slideshow_img_desc $slideshow_img_desc_cf_keys = []; for($j = 1; $j <= 6; $j++) { $slideshow_img_desc_cf_keys[] = 'slideshow_img'.$j.'_desc'; } foreach($slideshow_img_desc_cf_keys as $slideshow_img_desc_cf_key) { if(!empty($_POST[$slideshow_img_desc_cf_key])) { update_post_meta($post_id, $slideshow_img_desc_cf_key, sanitize_text_field($_POST[$slideshow_img_desc_cf_key])); } else { delete_post_meta($post_id, $slideshow_img_desc_cf_key, get_post_meta($post_id, $slideshow_img_desc_cf_key, true)); } } } add_action('save_post', 'save_my_cf'); ?>
このコード内で行っていることを自分なりにまとめますと、
- 2つのカスタムフィールド:基本情報(key:’basic_info_cf’)と スライドショー画像(key:’slideshow_img’)を設定
- 画像アップロードに必要なmultipart/form-dataの設定を追加
- 基本情報(key:’basic_info_cf’)の入力エリアの設定
- スライドショー画像(key:’slideshow_img’)の入力エリアを設定
- カスタムフィールドの値を保存する設定
を行っています。
これによりTOPページに設定した固定ページの編集時に2つのカスタムフィールドが表示されました。
1つ目の基本情報のカスタムフィールドに関しては問題なく保存され他のページで取得することができました。
しかし、2つ目のスライドショー画像のカスタムフィールドに関しては、意図通り
「画像1のファイル」
「画像1の説明文」
「画像2のファイル」
「画像2の説明文」
・
・
・
「画像6のファイル」
「画像6の説明文」
と表示されましたが、画像ファイルの保存時に意図していない挙動が起こります。
例えば、画像1、画像2にファイルをアップロードし、記事の更新を行うと、画像1と画像2が保存されましたが、その後に画像3のみをアップロードし記事の更新を行うと、画像3以外の画像が取得できなくなります。このカスタムフィールドで登録した画像はサーバー内の\wordpress\wp-content\uploads\2021\05に保存されるのですが、先ほどの例のような登録を行うと、画像1、画像2、画像3のファイルはディレクトリ内に存在していますが、1度目にアップロードした画像1と画像2のみ、情報を取得できません。
※追記:WordPress上でメディアライブラリを確認したところ、「05」(おそらく現在のMonth)というファイルがたくさんアップロードされており、それが原因と考えられます。ただ、そのファイルがアップロードされる理由が分からないです。
※追記2:データベースのwp_postmetaを見ると、記事を更新するとmeta_keyが_wp_attached_file、meta_valueが2021/05/のデータが6つ登録され、その後にアップロードした画像の分のみmeta_keyが_wp_attached_file、meta_valueが画像名のデータが追加されています。
これらの問題が起こるのは何が原因なのでしょうか?
また、今回は画像1のファイルと画像1の説明文を別々のkeyで登録・取得していますが、各画像のファイルと説明文をもっと良い方法で登録、取得する方法はありますでしょうか?
- トピック「カスタムフィールドで画像の保存時に他の画像が使えない」には新たに返信することはできません。