46
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

【WordPress】プラグインなしでカスタム投稿タイプにカスタムフィールド(テキスト&画像)を追加する方法

プラグインを使わずに、カスタム投稿タイプにカスタムフィールド(テキスト&画像)を追加する方法を書いていこうと思います。

まずはじめに

カスタム投稿タイプなどに限らずですが、基本はWordPressに何か機能を追加しようする場合などは、アクションフックやフィルターフックを利用して追加していきます。いろいろなフックを知ることで、好きなタイミングで任意の処理などを追加できるようになりますので、WordPress標準のアクションフック・フィルターフックは覚えておくといいと思います。今回は、initadmin_menusave_postpost_edit_form_tagというフックを利用していきます。

カスタム投稿タイプを追加

まずは、管理画面にカスタム投稿タイプを追加していきます。
initをフックしてregister_post_type関数を使ってカスタム投稿タイプを登録します。ちなみに、initの実行タイミングはWordPressのコアファイルの読み込みが終わり、HTTPのヘッダーを出力する前となります。

function create_post_type(){
  //カスタム投稿タイプがダッシュボードの編集画面で使用する項目を配列で用意
  $supports = array(
    'title',
    'editor',
    'author',
    'thumbnail',
    'revisions'
  );
  //カスタム投稿タイプを追加するための関数
  //第一引数は任意のカスタム投稿タイプ名
  register_post_type('hoge_custom_post',
    array(
      'label' => 'サンプルカスタム投稿',
      'public' => true, //フロントエンド上で公開する場合true
      'has_archive' => true, //アーカイブページを表示したい場合true
      'menu_position' => 3, //メニューを表示させる場所
      'supports' => $supports //ダッシュボードの編集画面で使用する項目
    )
  );
}
add_action('init','create_post_type');

作成したカスタム投稿タイプにカスタムフィールドを追加

次に、作成したカスタム投稿タイプにカスタムフィールドを追加していきます。
admin_menuをフックしてadd_meta_box関数でメタボックスを追加します。admin_menuの実行タイミングは管理画面が読み込まれた時です。

function add_custom_fields(){
    add_meta_box(
        'custom_setting', //編集画面セクションのHTML ID
        'カスタム情報', //編集画面セクションのタイトル、画面上に表示される
        'insert_custom_fields', //編集画面セクションにHTML出力する関数
        'hoge_custom_post', //投稿タイプ名
        'normal' //編集画面セクションが表示される部分
    );
}
add_action('admin_menu', 'add_custom_fields');

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_custom_fields(){
    global $post;
    //get_post_meta関数を使ってpostmeta情報を取得
    $hoge_name = get_post_meta(
                     $post->ID, //投稿ID
                     'hoge_name', //キー名
                     true //戻り値を文字列にする場合true(falseの場合は配列)
                 );
    $hoge_thumbnail = get_post_meta($post->ID,'hoge_thumbnail',true);
    echo '名前: <input type="text" name="hoge_name" value="'.$hoge_name.'" /><br>';
    echo '画像: <input type="file" name="hoge_thumbnail" accept="image/*" /><br>';
    if(isset($hoge_thumbnail) && strlen($hoge_thumbnail) > 0){
        //hoge_thumbnailキーのpostmeta情報がある場合は、画像を表示
        //$hoge_thumbnailには、後述するattach_idが格納されているので、wp_get_attachment_url関数にそのattach_idを渡して画像のURLを取得する
        echo '<img style="width: 200px;display: block;margin: 1em;" src="'.wp_get_attachment_url($hoge_thumbnail).'">';
    }
}

カスタムフィールドの保存処理

最後に、カスタムフィールドの値を保存する処理を書いていきます。
save_postをフックしてupdate_post_meta関数を使ってwp_postmetaテーブルに値を保存していきます。save_postの実行タイミングは投稿を保存した時です。また、画像の場合はwp_postsテーブルに画像情報を格納して、そのレコードのIDをwp_postmetaテーブルに保持させる形になっています。
※ 画像ファイル自体は、uploadsディレクトリ配下に置くので、パーミッションがない場合は権限を与えるようにしてください

function save_custom_fields( $post_id ) {
    if(isset($_POST['hoge_name'])){
        //hoge_nameキーで、$_POST['hoge_name']を保存
        update_post_meta($post_id, 'hoge_name', $_POST['hoge_name']);
    }else{
        //hoge_nameキーの情報を削除
        delete_post_meta($post_id, 'hoge_name');
    }

    if(isset($_FILES['hoge_thumbnail']) && $_FILES["hoge_thumbnail"]["size"] !== 0){
        $file_name = basename($_FILES['hoge_thumbnail']['name']);
        $file_name = trim($file_name);
        $file_name = str_replace(" ", "-", $file_name);

        $wp_upload_dir = wp_upload_dir(); //現在のuploadディクレトリのパスとURLを入れた配列
        $upload_file = $_FILES['hoge_thumbnail']['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['hoge_thumbnail']['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, 'hoge_thumbnail',$attach_id);
        }else{
            //保存失敗
            echo '画像保存に失敗しました';
            exit;
        }
    }
}
add_action('save_post', 'save_custom_fields');

最後に

以上の手順で、カスタム投稿タイプにカスタムフィールド(テキスト&画像)を追加することができます。あとは、画像のinput要素などはlabel要素を使ってリッチにしたり、画像がすでに登録されている場合はinput要素を非表示にするなどの処理を入れれば、いい感じのカスタムフィールドが作れると思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
46
Help us understand the problem. What are the problem?