WordPressでカスタム投稿タイプとメタボックスを使用して独自の投稿画面を作成する方法
目的
カスタム投稿タイプを自作します。
phpを使用して、Wordpress管理者が記事投稿をする際にカスタム投稿画面から記事を投稿できるようにします。 投稿を出力する際にもカスタム投稿タイプをキーにして投稿を取得できます。
以下メリットがあります。
- カスタム投稿タイプ毎のメタボックス(カスタムフィールド)を設定できる。(通常投稿のカスタムフィールドを使用するより、必要入力値漏れを抑える)
- 出力時にカスタム投稿タイプで判別ができる。(カテゴリ分け、タグ分けと同じように出力する場合の判断材料となる)
- 出力時にカスタム投稿タイプをキーにすることで、付加情報を付けやすい(schema.orgなど)
結果
サンプルとしてイベントを開催する記事専用の投稿画面を作成します。
wordpress管理画面にregister_post_type()を使用して、カスタム投稿タイプ「event」を作成します。
作成したカスタム投稿タイプ「event」にadd_meta_boxを使用してメタボックスの値として開催日付けを意図した「event-date」、イベントサブタイトルを意図した「event-description」を作成します。
single.phpにカスタム投稿タイプ「event」をキーにして投稿を取得し、メタボックスの値「event-date」、「event-description」を出力します。
▼カスタム投稿「イベント」でメタボックスを表示する。
方法
※function.phpに全て書くと管理が煩雑になるため外部ファイルに設定を記載し、function.phpから呼び出しています。
※外部ファイルは「include」ディレクトリを作成し、その中に格納しています。
▼前提 directory図
-function.php <--- 各外部ファイルの読み込みと関数実行
-single.php <--- カスタム投稿の内容を表示しているファイル
-include(dir)
-admin-custompost.php <--- カスタム投稿タイプを定義しているファイル
-admin-meta-event.php <--- メタボックスを定義しているファイル
カスタム投稿タイプ作成フロー
1カスタム投稿タイプの設定 register_post_type() (修正ファイル:function.php,admin-custompost.php) |
↓ |
2メタボックスの設定 add_meta_box() (修正ファイル:admin-meta-event.php) |
↓ |
3カスタム投稿タイプの出力 query_posts() (修正ファイル:single.php) |
1.カスタム投稿タイプの設定 register_post_type()
function.phpを編集し、これから自作するカスタム投稿用の関数をフックします。
admin-custompost.phpを編集し、WordPress管理画面に表示する設定を行います。
▼編集ファイル
・function.php(修正)
・admin-custompost.php(新規作成)
▼function.php
function.php内でadd_action()を使用して、各関数をフックします。各関数は外部ファイルに定義しています。
require()を使用して外部ファイルを読み込みます。
//カスタム投稿を定義
require ( dirname(__FILE__) . '/include/admin-custompost.php');
add_action('init', 'sample_custom_post_type');
//メタボックスを定義
require ( dirname(__FILE__) . '/include/admin-meta-event.php');
add_action('admin_menu', 'add_event_box');
add_action('save_post', 'save_event_box');
▼admin-custompost.php
関数sample_custom_post_type()を定義します。
この関数はregister_post_type()を使用して、Wordpress管理画面に出力するカスタム投稿ポストを登録します。
function sample_custom_post_type() {
$sampleLabels = array(
'name' => 'イベント',
'add_new_item' => 'イベントの登録',
'not_found' => 'イベントはありません。',
'new_item' => '新しいイベント',
'view_item' => 'イベントの表示',
'edit_item' => 'イベントの編集',
);
$sampleArray = array (
"labels" => $sampleLabels,
"hierarchical"=>false,
"public"=>true,
"query_var"=>false,
"supports"=>array(
"title",
"editor",
"thumbnail",
)
);
register_post_type('event' , $sampleArray);
}
2.メタボックスの設定 add_meta_box()
admin-meta-event.phpを作成し、カスタム投稿画面に出力するメタボックスの定義をします。
▼編集ファイル
・admin-meta-event.php(新規作成)
▼admin-meta-event.php
add_meta_box()を使用して、カスタム投稿画面に設定するメタボックスの設定をしています。
メタボックスとしての表示内容、登録処理は関数'event_info_form'で実行しています。
<?php
function add_event_box() {
add_meta_box('event_info', イベント情報', 'event_info_form', 'event', 'normal', 'high');
}
function event_info_form() {
global $post; //編集中データ
wp_nonce_field(wp_create_nonce(__FILE__), 'my_nonce'); //CSRF対策
?>
<table width="100%" >
<tr>
<td><textarea name="event-description" style="width: 100%;"><?php echo esc_html(get_post_meta($post->ID, '_event-description', true)); ?></textarea></td>
</tr>
<tr>
<td><input type="date" name="event-date" value="<?php echo esc_html(get_post_meta($post->ID, '_event-date', true)); ?>" style="width : 150px;" ></td>
</tr>
</table>
<?php
}
function save_event_box($post_id) {
// nonce値の比較、値が異なる場合処理をしない
$my_nonce = isset($_POST['my_nonce']) ? $_POST['my_nonce'] : null;
if(!wp_verify_nonce($my_nonce, wp_create_nonce(__FILE__))) {
return $post_id;
}
// 自動保存ルーチンであった場合処理をしない
if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return $post_id; }
// Edit権限を持たない場合は処理をしない
if(!current_user_can('edit_post', $post_id)) { return $post_id; }
// 値の格納 先頭にアンダーバーを記載することでカスタムフィールドとして出力されない
$eventProf = array (
'_event-description' => $_POST['event-description'] ,
'_event-date' => $_POST['event-date'] ,
);
//値の保存、$keyが空白ならDBに追加、$valueが前回と異なればDBを更新、$valueが空白ならDBから削除
foreach ( $eventProf as $key => $value ) {
if(get_post_meta($post_id, $key ) == ""){
add_post_meta($post_id, $key, $value, true);
}elseif($value != get_post_meta($post_id, $key, true)){
update_post_meta($post_id, $key, $value);
}elseif($value == ""){
delete_post_meta($post_id, $key, get_post_meta($post_id, $key, true));
}
}
}
?>
3.カスタム投稿タイプの出力 query_posts()
single.phpに上記登録したカスタム投稿とメタボックスの表示をします。
▼編集ファイル
・single.php(修正)
▼single.php
引数post_typeにカスタム投稿タイプとしてregister_post_typeに渡したeventを渡します。
作成した各メタボックスの値はget_post_meta()により取得します。
<?php
$args = array(
'post_type' => 'event',
'posts_per_page' => 10,
'paged' => $paged ,
);
$myposts = query_posts( $args );
foreach ( $myposts as $post ) : setup_postdata( $post );
echo esc_html(get_post_meta($post->ID, '_event_date', true));
echo esc_html(get_post_meta($post->ID, '_event_description', true));
endforeach;
wp_reset_postdata();
?>
参考
- register_post_type() - WordPress Codex
- add_meta_box() - WordPress Codex
- query_posts() - WordPress Codex
- wp_nonce_field() -WordPress Codex
- add_post_meta() -WordPress Codex
- update_post_meta() -WordPress Codex
- delete_post_meta() -WordPress Codex
- wp_reset_postdata() -WordPress Codex
- add_action() -WordPress Codex
その他詳細
mySQL DBについて
登録だけした場合このような感じになります。(投稿IDは40)
XXXX_は自分で設定したデータベース接頭語が入る。
mysql> select * from XXXX_posts where ID = 40 ;
+----+-------------+---------------------+---------------------+--------------+--------------------------+--------------+-------------+----------------+-------------+---------------+-------------------+---------+--------+---------------------+---------------------+-----------------------+-------------+----------------
---------------------------+------------+-----------+----------------+---------------+
| ID | post_author | post_date | post_date_gmt | post_content | post_title | post_excerpt | post_status | comment_status | ping_status | post_password | post_name | to_ping | pinged | post_modified | post_modified_gmt | post_content_filtered | post_parent | guid | menu_order | post_type | post_mime_type | comment_count |
+----+-------------+---------------------+---------------------+--------------+--------------------------+--------------+-------------+----------------+-------------+---------------+-------------------+---------+--------+---------------------+---------------------+-----------------------+-------------+-------------------------------------------+------------+-----------+----------------+---------------+
| 40 | 1 | 2019-03-13 23:08:41 | 2019-03-13 14:08:41 | | サンプルイベント | | publish | open | closed | | %e3%82%b5%e・・・ | | | 2019-03-13 23:10:57 | 2019-03-13 14:10:57 | | 0 | https://XXXX/?post_type=event&p=40 | 0 | event | | 0 |
+----+-------------+---------------------+---------------------+--------------+--------------------------+--------------+-------------+----------------+-------------+---------------+-------------------+---------+--------+---------------------+---------------------+-----------------------+-------------+-------------------------------------------+------------+-----------+----------------+---------------+
mysql> select * from XXXX_postmeta where post_id = 40 ;
+---------+---------+--------------------+--------------------------------+
| meta_id | post_id | meta_key | meta_value |
+---------+---------+--------------------+--------------------------------+
| 14 | 40 | _edit_last | 1 |
| 15 | 40 | _edit_lock | 1552486122:1 |
| 16 | 40 | _event-description | サンプルメタボックス |
| 17 | 40 | _event-date | 2019-03-14 |
+---------+---------+--------------------+--------------------------------+
フック可能な関数名(wp-includes/post.phpの中)
※ただpost.php内をgrepしたのみ
[root@xxxxxxxxxxxxxxxxxf wp-includes]# grep do_action ./post.php
do_action( 'registered_post_type', $post_type, $post_type_object );
do_action( 'unregistered_post_type', $post_type );
do_action( 'post_stuck', $post_id );
do_action( 'post_unstuck', $post_id );
do_action( 'before_delete_post', $postid );
do_action( 'delete_post', $postid );
do_action( 'deleted_post', $postid );
do_action( 'after_delete_post', $postid );
do_action( 'wp_trash_post', $post_id );
do_action( 'trashed_post', $post_id );
do_action( 'untrash_post', $post_id );
do_action( 'untrashed_post', $post_id );
do_action( 'trash_post_comments', $post_id );
do_action( 'trashed_post_comments', $post_id, $statuses );
do_action( 'untrash_post_comments', $post_id );
do_action( 'untrashed_post_comments', $post_id );
do_action( 'pre_post_update', $post_ID, $data );
do_action( 'edit_attachment', $post_ID );
do_action( 'attachment_updated', $post_ID, $post_after, $post_before );
do_action( 'add_attachment', $post_ID );
do_action( "edit_post_{$post->post_type}", $post_ID, $post );
do_action( 'edit_post', $post_ID, $post );
do_action( 'post_updated', $post_ID, $post_after, $post_before );
do_action( "save_post_{$post->post_type}", $post_ID, $post, $update );
do_action( 'save_post', $post_ID, $post, $update );
do_action( 'wp_insert_post', $post_ID, $post, $update );
do_action( "edit_post_{$post->post_type}", $post->ID, $post );
do_action( 'edit_post', $post->ID, $post );
do_action( "save_post_{$post->post_type}", $post->ID, $post, true );
do_action( 'save_post', $post->ID, $post, true );
do_action( 'wp_insert_post', $post->ID, $post, true );
do_action( 'transition_post_status', $new_status, $old_status, $post );
do_action( "{$old_status}_to_{$new_status}", $post );
do_action( "{$new_status}_{$post->post_type}", $post->ID, $post );
do_action( 'delete_attachment', $post_id );
do_action( 'delete_post', $post_id );
do_action( 'deleted_post', $post_id );
do_action( 'clean_post_cache', $post->ID, $post );
do_action( 'clean_page_cache', $post->ID );
do_action( 'clean_attachment_cache', $id );
do_action( 'private_to_published', $post->ID );
do_action( 'xmlrpc_publish_post', $post_id );