我們今天的目標,就是製作一個微型圖書館館藏設施,我們設定user case是要使用以建立文章的模式,並且可以在上面做處理,並且加入分類的功能,備註一個事項,我在高中時很喜歡拿人家做的小專案的實現,來做第二個二次仿作,但有些是為了魔以模仿情境為由,實際上做出來的的功能是有,但效果是否良好更得考量到UX這些,所以請大家要斟酌。
首先我們會使用到我們的register_post_type來做第一個,這個功能是會在顯示page與post這邊,你可能可以常常看見外掛在page下面有不同的名稱,像是testimonial或者是中文的顧客回饋之類的,這是用這個方式來實作的,而他可以做出什麼取決你的想像力,你可以從做一個簡單的作品集,也可以複雜的eCommerce products像是woocommerce來實作,之後你也可以把post當git tree的每個commit,不過不知道是不是會有人這樣搞就是了。
add_action( 'init', 'goranger_book_collection_post_types' );
function goranger_book_collection_post_types() {
register_post_type( 'book', [
// Post type 的參數們
'public' => true,
'publicly_queryable' => true,
'show_in_rest' => true,
'show_in_nav_menus' => true,
'show_in_admin_bar' => true,
'exclude_from_search' => false,
'show_ui' => true,
'show_in_menu' => true,
'menu_icon' => 'dashicons-book',
'hierarchical' => false,
'has_archive' => 'books',
'query_var' => 'book',
'map_meta_cap' => true,
// 對於url的形式的覆寫
'rewrite' => [
'slug' => 'books',
'with_front' => false,
'pages' => true,
'feeds' => true,
'ep_mask' => EP_PERMALINK,
],
'supports' => [
'title',
'editor',
'excerpt',
'thumbnail'
],
// 文字標題
'labels' => [
'name' => 'Books',
'singular_name' => 'Book',
'add_new' => 'Add New',
'add_new_item' => 'Add New Book',
'edit_item' => 'Edit Book',
'new_item' => 'New Book',
'view_item' => 'View Book',
'view_items' => 'View Books',
'search_items' => 'Search Books',
'not_found' => 'No books found.',
'not_found_in_trash' => 'No books found in Trash.',
'all_items' => 'All Books',
'archives' => 'Book Archives',
'attributes' => 'Book Attributes',
'insert_into_item' => 'Insert into book',
'uploaded_to_this_item' => 'Uploaded to this book',
'featured_image' => 'Book Image',
'set_featured_image' => 'Set book image',
'remove_featured_image' => 'Remove book image',
'use_featured_image' => 'Use as book image',
'filter_items_list' => 'Filter books list',
'items_list_navigation' => 'Books list navigation',
'items_list' => 'Books list',
'item_published' => 'Book published.',
'item_published_privately' => 'Book published privately.',
'item_reverted_to_draft' => 'Book reverted to draft.',
'item_scheduled' => 'Book scheduled.',
'item_updated' => 'Book updated.'
]
] );
}
在這裡比較重要的是文字標題的部分,在此方如果沒有定義,他全部就會轉化成page,其實這並不是讓人很開心的一件事情,但願以後是有個hook能夠把關鍵字給做簡單的replace,在對於特別的參數做不同的設定。
還記得我們前幾天提到的capabilities嗎?就是那一個莫名的manage_options
,如果你又自己的設定自己的cap,那麼你可以使用自己的角色權限,來制定你的頁面只有什麼權限的人可以使用,有別於加入很多條件來選擇current_user_can,cap來做的話,更加的有組織性。
如果是想加入一個簡單的tas的話,是可以在register的陣列中加入'taxonomies'=>['post_tag']
來做到,不過我們希望我們的名字是不一樣的,可以換名字叫做genre
,並且依照官方的文件來做那些需求的參數,我們也在後面會使用到get_taxonomy
與the_terms
來將我們的tax可以有更多的操作性。
add_action( 'init', 'goranger_books_register_taxonomies' );
function goranger_books_register_taxonomies() {
register_taxonomy( 'genre', 'book', [
'public' => true,
'show_in_rest' => true,
'show_ui' => true,
'show_in_nav_menus' => true,
'show_tagcloud' => true,
'show_admin_column' => true,
'hierarchical' => true,
'query_var' => 'genre',
'rewrite' => [
'slug' => 'genre',
'with_front' => false,
'hierarchical' => false,
'ep_mask' => EP_NONE
],
'labels' => [
'name' => 'Genres',
'singular_name' => 'Genre',
'menu_name' => 'Genres',
'name_admin_bar' => 'Genre',
'search_items' => 'Search Genres',
'popular_items' => 'Popular Genres',
'all_items' => 'All Genres',
'edit_item' => 'Edit Genre',
'view_item' => 'View Genre',
'update_item' => 'Update Genre',
'add_new_item' => 'Add New Genre',
'new_item_name' => 'New Genre Name',
'not_found' => 'No genres found.',
'no_terms' => 'No genres',
'items_list_navigation' => 'Genres list navigation',
'items_list' => 'Genres list',
// Hierarchical only.
'select_name' => 'Select Genre',
'parent_item' => 'Parent Genre',
'parent_item_colon' => 'Parent Genre:'
]
] );
}
再增加完這段後,你可以看見在submenu之中,你會多了一個新的取代tag的選項,假如你有把我文章中的程式碼試著加進去。
好了,接下來就是我們所謂的更多的資訊要放進我們的post,因為我們post原始的資訊欄位有限,metadata是個對於要加上好幾十種資訊的解決方法,而他會被儲存在postmeta
這個表之中,有興趣開mysql看看meta是怎麼被儲存的,我們這邊使用到的register_post_meta
。
add_action( 'init', 'goranger_books_register_meta' );
function goranger_books_register_meta() {
register_post_meta( 'book', 'book_author', [
'single' => true,
'show_in_rest' => true,
'sanitize_callback' => function( $value ) {
return wp_strip_all_tags( $value );
}
] );
}
而我們在操作metadata的時候更容易些,只需要post id
,就可以用add_post_meta或是get_post_meta來做到,大部分的都會是陣列回傳,所以可以在操作前先進行型態處理,而我們這邊使用註冊完後,就得加入所謂的meta_box,來做使用,將註冊的型態與之後增加的表格做連結。
說到metabox其實有分兩中,一種是在跟在編輯器下面的(如果你是5版以下,或是theme已經把guntenburg編輯器關閉),另外一種是在一旁的,而我們是做在下面的,主要是由$context來做處理,那我們緊接著就來增加我們的metaboxes,並且加入我們的表格來與meta_data連接。
add_action( 'add_meta_boxes_book', 'goranger_book_register_meta_boxes' );
function goranger_book_register_meta_boxes() {
add_meta_box(
'goranger-book-details',
'Book Details',
'goranger_book_details_meta_box',
'book',
'advanced',
'high'
);
}
function goranger_book_details_meta_box( $post ) {
// 取得現在的作者,不過我們還沒設定值所以為空
$author = get_post_meta( $post->ID, 'book_author', true );
// 我們增加我們的nonce field
wp_nonce_field( basename( __FILE__ ), 'goranger-book-details' ); ?>
<p>
<label>
Book Author:
<br />
<input type="text" name="goranger-book-author" value="<?php echo esc_attr( $author ); ?>" />
</label>
</p>
<?php
}
在加入這些後,我們也需要接我們的表格回傳的內容回來,我們會先驗證我們的nonce是否正確來保證安全性,以及使用者是否逾權基本的檢查,再來就是加入是否觸發了wp_autosave,這個其實是讓人很煩躁的功能,真希望他們可以只針對內容就好,目前我也還沒找出第二個不要對同一個頁面發出post觸發全部的連接的解決方式,而不只是autosave,回朔版本以及執行ajax都會觸發post,所以我們都要作防護,如果都通過就是將我們的資料做替換設定。
add_action( 'save_post_book', 'goranger_book_save_post', 10, 2 );
function goranger_book_save_post( $post_id, $post ) {
if (
! isset( $_POST['goranger-book-details'] ) ||
! wp_verify_nonce( $_POST['goranger-book-details'], basename( __FILE__ ) )
) {
return;
}
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return;
}
if (
wp_is_doing_ajax() ||
wp_is_post_autosave( $post_id ) ||
wp_is_post_revision( $post_id )
) {
return;
}
$old_author = get_post_meta( $post_id, 'book_author', true );
$new_author = isset( $_POST['goranger-book-author'] )
? wp_strip_all_tags( $_POST['goranger-book-author'] )
: '';
if ( ! $new_author && $old_author ) {
delete_post_meta( $post_id, 'book_author' );
} elseif ( $new_value !== $old_value ) {
update_post_meta( $post_id, 'book_author', $new_value );
}
}
這樣我們就完成了一個很簡易的加入圖書的功能了!這邊的程式碼是節錄威廉大師的範例程式碼,並且加以改來做講解,而這個基礎的運用,你也可以加工成能夠更快速的加入書本,假如你還要加入ISBN之類的,可以接上他們的API來做間接的應用,你如果覺得這個太小了,也可以去看woocommerce是怎麼實作將post做成product的,並且他在meta_box的操作是非常直得學習的,有著更複雜的表格操作,很適合新手學完基礎後去參考如何精進!
post-types
resiter_post_type
get_post_type_labels
get_post_type_capabilities
add_meta_boxed
Professional WordPress Plugin Development
How to Create Custom Post Types in WordPress
https://www.smashingmagazine.com/2012/11/complete-guide-custom-post-types/