[WordPress]カスタムフィールドをクイック編集で保存する方法について

  • 更新日:
  • 公開日:

カスタムフィールドをクイック編集で保存する方法について。後々実装しようとしたときに調べ直しそうな流れなのでカスタマイズ内容をメモしておきます。

大まかに5つのステップで実装できます。

カスタムフィールドをクイック編集で保存する

quickedit_custom_column00

分かりやすいように、作業に入る前に予め記事へカスタムフィールドを追加しておきましょう。

投稿の編集ページ右上にある「表示オプション」をクリックし、「カスタムフィールド」にチェックを入れてカスタムフィールドの編集ボックスを表示します。

今回私は名前を「weather」にして天気情報を保存するカスタムフィールドを作成しました。

(以降のソースコードはjQuery以外、functions.phpに記述します。)

2014年9月30日追記:

カスタムフィールドをチェックボックスで保存するソースコードも追加してみました。

1.投稿一覧に項目を追加する

まず始めに、投稿一覧に「今日の天気」を表示するための項目を追加します。項目の追加にはmanage_posts_columnsフックを使用します。

function my_posts_columns( $defaults ) {
    $defaults['weather'] = '今日の天気';
    $defaults['display'] = '天気情報を表示';

    return $defaults;
}
add_filter( 'manage_posts_columns', 'my_posts_columns' );

今回は項目を1つだけ追加していますが、もし複数追加したい場合は上のように$defaultsのキーに追加したいID名を、値に表示するラベルをさらに記述しましょう。

2.投稿一覧に追加した項目に値を表示する

次に、追加した項目に記事毎の天気情報(カスタムフィールド)を表示してみましょう。これにはmanage_posts_custom_columnフックを使用します。

function my_posts_custom_column( $column, $post_id ) {
    switch ( $column ) {
        case 'weather':
            $post_meta = get_post_meta( $post_id, 'weather', true );
            if ( $post_meta ) {
                echo $post_meta;
            } else {
                echo ''; //値が無い場合の表示
            }
            break;
        case 'display':
            //チェックボックスの場合
            if ( !!get_post_meta( $post_id , 'display' , true ) ) {
                $checked = 'checked';
            } else {
                $checked = '';
            }
            echo "<input type='checkbox' readonly $checked/>";
            break;
    }
}
add_action( 'manage_posts_custom_column' , 'my_posts_custom_column', 10, 2 );

第一引数には追加した項目のIDが渡されるので、これで処理を分岐させます。第二引数で渡される記事のIDを使ってget_post_meta()でカスタムフィールドの値を表示します。

3.クイック編集にカスタムフィールド用の入力フォームを表示する

それではクイック編集でカスタムフィールドに値を設定できるよう、入力フォームを表示しましょう。これにはquick_edit_custom_boxフックを使います。

function display_my_custom_quickedit( $column_name, $post_type ) {
    static $print_nonce = TRUE;
    if ( $print_nonce ) {
        $print_nonce = FALSE;
        wp_nonce_field( 'quick_edit_action', $post_type . '_edit_nonce' ); //CSRF対策
    }

    ?>
    <fieldset class="inline-edit-col-right inline-custom-meta">
        <div class="inline-edit-col column-<?php echo $column_name ?>">
            <label class="inline-edit-group">
                <?php
                switch ( $column_name ) {
                    case 'weather':
                        ?><span class="title">今日の天気</span><input name="weather" /><?php
                        break;
                    case 'display':
                        //チェックボックスの場合
                        ?><span class="title">天気情報を表示</span><input name="display" type="checkbox" /><?php
                        break;
                }
                ?>
            </label>
        </div>
    </fieldset>
<?php
}
add_action( 'quick_edit_custom_box', 'display_my_custom_quickedit', 10, 2 );

項目に値を表示したときと同じように、第一引数で渡ってくる項目のID名で分岐させます。これでクイック編集にカスタムフィールド用の項目が表示できます。

quickedit_custom_column01

しかし値の表示ができていません。ここで使ったフックには記事のIDが渡ってこないのでget_post_meta()を使った値の表示は難しいです。

なので、これにはjQueryを使います。

4.jQueryで動的にクイック編集の値を書き換える

まず、値を操作するJavascriptファイルを読み込むコードを書きます。admin_footer-(hookname)フックを使って管理ページのフッターで関数を実行させ、その中でファイルを読み込むタグをechoしましょう。”hookname”に関数を実行したいページの名前(ファイル名)を指定します。

投稿一覧の名前は”edit.php”なので、「admin_footer-edit.php」というフック名にします。

function my_admin_edit_foot() {
    global $post_type;
    $slug = 'post'; //他の一覧ページで動作しないように投稿タイプの指定をする

    if ( $post_type == $slug ) {
        echo '<script type="text/javascript" src="', get_stylesheet_directory_uri() .'/admin/js/admin_edit.js', '"></script>';
    }
}
add_action('admin_footer-edit.php', 'my_admin_edit_foot');

この例ではテーマフォルダに「admin/js」というフォルダを作成し、その中の「admin_edit.js」ファイルを読み込むパスになっています。同じようにテーマフォルダ内にフォルダとJavascriptファイルを作成して下さい。(「wp-content/themes/テーマ名/」の中に作成します)

スクリプトファイル(admin_edit.js)の中身は以下です。

(function($) {
    var $wp_inline_edit = inlineEditPost.edit;

    inlineEditPost.edit = function( id ) {
        $wp_inline_edit.apply( this, arguments );

        var $post_id = 0;
        if ( typeof( id ) == 'object' )
            $post_id = parseInt( this.getId( id ) );

        if ( $post_id > 0 ) {
            var $edit_row = $( '#edit-' + $post_id );
            var $post_row = $( '#post-' + $post_id );

            //今日の天気
            var $weather = $( '.column-weather', $post_row ).html();
            $( ':input[name="weather"]', $edit_row ).val( $weather );

            //天気情報を表示(チェックボックス)
            var $display = !! $('.column-display>*', $post_row).attr('checked');
            $( ':input[name="display"]', $edit_row ).attr('checked', $display );
        }
    };

})(jQuery);

任意のカスタムフィールド名を指定するときに修正が必要なのは15行目と17行目です。15行目には項目のID名を、17行目にはカスタムフィールドの名前を指定すると値が表示されるようになります。

5.カスタムフィールドの保存処理をする

これまでのソースコードでクイック編集に値の表示までできました。最後に値の保存処理をします。

記事の保存処理時にはsave_postというフックが用意されているのでコレを使います。

function save_custom_meta( $post_id ) {
    $slug = 'post'; //カスタムフィールドの保存処理をしたい投稿タイプを指定

    if ( $slug !== get_post_type( $post_id ) ) {
        return;
    }
    if ( !current_user_can( 'edit_post', $post_id ) ) {
        return;
    }

    $_POST += array("{$slug}_edit_nonce" => '');
    if ( !wp_verify_nonce( $_POST["{$slug}_edit_nonce"], 'quick_edit_action' ) ) {
        return;
    }

    if ( isset( $_REQUEST['weather'] ) ) {
        update_post_meta( $post_id, 'weather', $_REQUEST['weather'] );
    }

    //チェックボックスの場合
    if ( isset( $_REQUEST['display'] ) ) {
        update_post_meta($post_id, 'display', TRUE);
    } else {
        update_post_meta($post_id, 'display', FALSE);
    }
}
add_action( 'save_post', 'save_custom_meta' );

17行目でカスタムフィールドの値を保存しています。じゃあこれより上のソースコードは何かというと、以下の判定をしています。

  • 4行目で投稿タイプの判定
  • 7行目でユーザーに編集権限があるかの判定
  • 12行目でノンス判定によるセキュリティ対策

これでクイック編集によるカスタムフィールドの操作ができるようになりました。

おまけ: 固定ページやカスタム投稿タイプはどうするの?

固定ページやカスタム投稿タイプで、同じようにクイック編集でカスタムフィールドを弄るには以下の様に対応します。

1と2のフック名を固定ページ、カスタム投稿タイプ用に変更する

1(投稿一覧に項目追加)と2(項目に値表示)で使っているフックには固定ページ用、投稿タイプ用のフックがあります。それぞれ以下のフックを使っていますが、

  • manage_posts_columns
  • manage_posts_custom_column

これらは固定ページで使うなら

  • manage_pages_columns
  • manage_pages_custom_column

とし、カスタム投稿タイプなら

  • manage_投稿タイプ名_posts_columns
  • manage_投稿タイプ名_posts_custom_column

として使います。例えば投稿タイプ名が”news“だとしたら、1のソースコードで使ったフック名は「manage_news_posts_columns」になります。

3のソースコードは1で使ったフック名の投稿タイプで自動的に実行される

3(クイック編集にフィールド表示)で使ったフックquick_edit_custom_boxは特に弄る必要はないようです。実際に動かして調べた所、1で使うフック名を固定ページ用、投稿タイプ用に変更すると自動的にクイック編集にフィールドが表示されました。

4と5はソースコード内の投稿タイプ判定でOK

4(スクリプトの読み込み)と5(保存処理)それぞれには予め投稿タイプを判定して処理しています。

4なら3行目で、5なら2行目に投稿タイプを各々指定したらOKです。

参考ページ:

Plugin API/Filter Reference/manage posts columns « WordPress Codex

Plugin API/Action Reference/manage posts custom column « WordPress Codex

Plugin API/Action Reference/quick edit custom box « WordPress Codex

書いた人

Symbol Mark

Ryoichi(しつ)

除菌ティッシュを買い込んで使いきれずによく乾かす人。

療養目的で退職し、どうやって生きていくか模索中。最近は勉強目的でLaravelやVue.js弄ったり、趣味で音で遊んでます。

※2019年10月16日現在ブログリニューアル中です。崩れなどが発生していたらすみません。

うぇぶ: @s_ryone