WordPress 中的自定義數據庫表:第 2 部分

已發表: 2022-08-01

在我們關於 WordPress 中的自定義數據庫表系列的第一部分中,我們研究瞭如何從自己的自定義插件中創建自定義數據庫表。 在第 2 部分中,我們將引導您了解如何修改和修改 WordPress 自定義表,包括如何在刪除插件時刪除自定義數據庫表。 此外,我們將解釋如何在管理區域中為插件添加菜單項,以及在自定義數據表中查看或添加條目的選項。

如何在插件刪除時刪除您的自定義表格

為了在插件本身被刪除時刪除表,我們需要使用 WordPress 提供的register_uninstall_hook()函數來設置插件的卸載掛鉤。

 function uninstall_students_plugin(){ global $wpdb; $table_name = $wpdb->prefix . 'students'; $wpdb->query("DROP TABLE IF EXISTS $table_name"); } register_uninstall_hook(__FILE__,'uninstall_students_plugin');

如果您現在停用並刪除插件,您現在應該會看到數據庫中的“students”表已成功刪除。

自定義表管理菜單項和頁面

在本節中,我們將向您展示如何為“學生”自定義表添加管理頁面及其菜單項。

管理員菜單項

這是您可以嘗試的一段代碼 - 將其附加到當前插件 PHP 文件中:

 function students_custom_table_admin_menu() { add_menu_page(__('Students', 'students_custom_table'), __('Students', 'students_custom_table'), 'activate_plugins', 'students', 'students_custom_table_page_handler', 'dashicons-welcome-learn-more', '5'); add_submenu_page('students', __('Students', 'students_custom_table'), __('Students', 'students_custom_table'), 'activate_plugins', 'students', 'students_custom_table_page_handler'); add_submenu_page('students', __('Add new', 'students_custom_table'), __('Add new', 'students_custom_table'), 'activate_plugins', 'students_form', 'students_custom_table_page_handler_add_form'); } add_action('admin_menu', 'students_custom_table_admin_menu');

現在在管理區域中,您應該會看到類似這樣的內容。

正如預期的那樣,當您單擊任何圖標時,您會看到沒有顯示任何內容。 我們將在下一節中定義頁面內容,但首先,讓我們檢查上面的代碼行以了解它們是如何工作的。

使用 Pressidium 託管您的網站

60 天退款保證

查看我們的計劃

因為我們要創建一個頂級菜單項和兩個子項,所以我們同時使用了 WordPress 提供的 add_menu_page() 函數和 add_submenu_page()。 這些函數接受以下參數:

 add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $position )
  • $page_title是需要定義的,它基本上是您在選擇此菜單項時被重定向到的頁面的標題標籤的第一部分。 在我們的例子中, students_custom_table
  • $menu_title - 也是必需的 - 是用於菜單的文本。 我們選擇“學生”作為文本。
  • $capability是用戶顯示此菜單所需的能力。 在我們的例子中,我們選擇了activate_plugins權限。 默認情況下,它只提供給超級用戶和管理員。 如果您想了解哪個角色或能力適合您的需求,可以查閱相關的官方文檔。
  • $menu_slug是我們的students字符串,在許可之後出現。 它也是必需的並且應該是唯一的。 它僅使用與 sanitize_key() 兼容的小寫字母數字、破折號和下劃線字符。
  • $icon_url是一個可選參數,是鏈接到將用於菜單項的圖標文件的 URL。 我們從 dashicons WordPress 庫中選擇了一個。
  • $position 是您可以選擇在此項目應出現的菜單順序中設置位置的位置。
 add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $position )

除了與add_menu_page相同的參數外,我們還看到

  • $parent_slug參數是父菜單的必需字符串,在我們的例子中是students
  • $function參數是您定義將創建設置頁面內容的回調函數的地方。 在我們的例子中, students_custom_table_page_handler()用於學生顯示表, students_custom_table_page_handler_add_form()用於添加學生的表單。
    我們還沒有聲明這些函數,但我們稍後會聲明。

自定義表格記錄顯示

讓我們從添加將在“學生”菜單項下顯示學生表的代碼開始。

為了顯示管理表數據,WordPress 擴展了WP_List_Table內置類。 WP_List_Table類在 wp-admin/includes/class-wp-list-table.php 文件中作為私有類引入。 私有類被命名為私有,因為它們僅供其他核心類和函數使用,而不是開發人員使用。

但是,WordPress 為您提供了通過擴展來重新定義此類的能力。 所以,我們要做的是創建一個自定義類,我們將在其中重新定義WP_List_Table類的屬性和方法,以便用我們想要的數據填充管理表。 我們將類命名為“Students_Custom_Table_List_Table”,我們需要的代碼行如下。

 if (!class_exists('WP_List_Table')) { require_once(ABSPATH . 'wp-admin/includes/class-wp-list-table.php'); } class Students_Custom_Table_List_Table extends WP_List_Table { function __construct() { global $status, $page; parent::__construct(array( 'singular' => 'person', 'plural' => 'persons', )); } function column_default($item, $column_name) { return $item[$column_name]; } function column_age($item) { return '<em>' . $item['age'] . '</em>'; } function column_ip($item) { return '<em>' . $item['ip_address'] . '</em>'; } function column_name($item) { $actions = array( 'edit' => sprintf('<a href="?page=students_form&id=%s">%s</a>', $item['id'], __('Edit', 'students_custom_table')), 'delete' => sprintf('<a href="?page=%s&action=delete&id=%s">%s</a>', $_REQUEST['page'], $item['id'], __('Delete', 'students_custom_table')), ); return sprintf('%s %s', $item['name'], $this->row_actions($actions) ); } function column_cb($item) { return sprintf( '<input type="checkbox" name="id[]" value="%s" />', $item['id'] ); } function get_columns() { $columns = array( 'cb' => '<input type="checkbox" />', //Render a checkbox instead of text 'name' => __('Name', 'students_custom_table'), 'email' => __('E-Mail', 'students_custom_table'), 'age' => __('Age', 'students_custom_table'), 'ip_address' => __('IP address', 'students_custom_table'), ); return $columns; } function get_sortable_columns() { $sortable_columns = array( 'name' => array('name', true), 'email' => array('email', false), 'age' => array('age', false), 'ip_address' => array('ip_address', false), ); return $sortable_columns; } function get_bulk_actions() { $actions = array( 'delete' => 'Delete' ); return $actions; } function process_bulk_action() { global $wpdb; $table_name = $wpdb->prefix . 'students'; // do not forget about tables prefix if ('delete' === $this->current_action()) { $ids = isset($_REQUEST['id']) ? $_REQUEST['id'] : array(); if (is_array($ids)) $ids = implode(',', $ids); if (!empty($ids)) { $wpdb->query("DELETE FROM $table_name WHERE id IN($ids)"); } } } function prepare_items() { global $wpdb; $table_name = $wpdb->prefix . 'students'; $per_page = 5; $columns = $this->get_columns(); $hidden = array(); $sortable = $this->get_sortable_columns(); $this->_column_headers = array($columns, $hidden, $sortable); $this->process_bulk_action(); $total_items = $wpdb->get_var("SELECT COUNT(id) FROM $table_name"); $paged = isset($_REQUEST['paged']) ? ($per_page * max(0, intval($_REQUEST['paged']) - 1)) : 0; $orderby = (isset($_REQUEST['orderby']) && in_array($_REQUEST['orderby'], array_keys($this->get_sortable_columns()))) ? $_REQUEST['orderby'] : 'name'; $order = (isset($_REQUEST['order']) && in_array($_REQUEST['order'], array('asc', 'desc'))) ? $_REQUEST['order'] : 'asc'; $this->items = $wpdb->get_results($wpdb->prepare("SELECT * FROM $table_name ORDER BY $orderby $order LIMIT %d OFFSET %d", $per_page, $paged), ARRAY_A); $this->set_pagination_args(array( 'total_items' => $total_items, 'per_page' => $per_page, 'total_pages' => ceil($total_items / $per_page) )); } }

如果您仔細檢查代碼,您會注意到列“age”和“ip_address”是如何定義的。 現在我們可以繼續並定義最終將為我們提供“學生”管理屏幕內容的函數。

 function students_custom_table_page_handler() { global $wpdb; $table = new Students_Custom_Table_List_Table(); $table->prepare_items(); $message = ''; if ('delete' === $table->current_action()) { $message = '<div class="updated below-h2"><p>' . sprintf(__('Items deleted: %d', 'students_custom_table'), count($_REQUEST['id'])) . '</p></div>'; } ?> <div class="wrap"> <div class="icon32 icon32-posts-post"><br></div> <h2><?php _e('Students', 'students_custom_table')?> <a class="add-new-h2" href="<?php echo get_admin_url(get_current_blog_id(), 'admin.php?page=students_form');?>"><?php _e('Add new', 'students_custom_table')?></a> </h2> <?php echo $message; ?> <form method="GET"> <input type="hidden" name="page" value="<?php echo $_REQUEST['page'] ?>"/> <?php $table->display() ?> </form> </div> <?php }

簡而言之,我們首先創建了自定義Students_Custom_Table_List_Table類的實例,然後創建了包含學生表數據的 html 元素。 您現在應該能夠看到顯示的表格,但請注意它將是空的。

現在我們已經完成了,讓我們添加一些學生。!

創建表單以添加我們的自定義數據

正如我們之前提到的,負責添加學生的函數將是students_custom_table_page_handler_add_form()

 function students_custom_table_page_handler_add_form() { global $wpdb; $table_name = $wpdb->prefix . 'students'; $message = ''; $notice = ''; $default = array( 'id' => 0, 'name' => '', 'email' => '', 'age' => null, 'ip_address' => null, ); if (wp_verify_nonce($_REQUEST['nonce'], basename(__FILE__))) { $item = shortcode_atts($default, $_REQUEST); $result = $wpdb->insert($table_name, $item); $item['id'] = $wpdb->insert_id; if ($result) { $message = __('Item was successfully saved', 'students_custom_table'); } else { $notice = __('There was an error while saving item', 'students_custom_table'); } } add_meta_box('students_form_meta_box', 'Student data', 'students_custom_table_students_form_meta_box_handler', 'student', 'normal', 'default'); ?> <div class="wrap"> <div class="icon32 icon32-posts-post"><br></div> <h2><?php _e('Student', 'students_custom_table')?> <a class="add-new-h2" href="<?php echo get_admin_url(get_current_blog_id(), 'admin.php?page=students');?>"><?php _e('back to list', 'students_custom_table')?></a> </h2> <?php if (!empty($notice)): ?> <div class="error"><p><?php echo $notice ?></p></div> <?php endif;?> <?php if (!empty($message)): ?> <div class="updated"><p><?php echo $message ?></p></div> <?php endif;?> <form method="POST"> <input type="hidden" name="nonce" value="<?php echo wp_create_nonce(basename(__FILE__))?>"/> <input type="hidden" name="id" value="<?php echo $item['id'] ?>"/> <div class="metabox-holder"> <div> <div> <?php do_meta_boxes('student', 'normal', $item); ?> <input type="submit" value="<?php _e('Save', 'students_custom_table')?>" class="button-primary" name="submit"> </div> </div> </div> </form> </div> <?php }

正如您在代碼中看到的,我們首先設置了一個$default數組,它將用於我們的新記錄。

接下來,在我們驗證請求已發布並且我們擁有正確的 nonce 之後,我們使用 shortcode_atts()。 這是一個非常有用的內置 WordPress 功能,它結合了給定的參數並在需要時填充默認值。

最後,我們添加自定義元框並將數據插入自定義表,收到一條消息,通知我們該過程已成功。

出於本教程的目的,我們跳過了一些元素,如果在現實世界中使用,您會想要添加這些元素。 其中包括通過定義添加重複名稱或電子郵件時會發生什麼等操作來驗證添加到數據庫中的信息。

最後但同樣重要的是,我們應該為我們的自定義元框添加一個處理程序:

 function students_custom_table_students_form_meta_box_handler($item) { ?> <table cellspacing="2" cellpadding="5" class="form-table"> <tbody> <tr class="form-field"> <th valign="top" scope="row"> <label for="name"><?php _e('Name', 'students_custom_table')?></label> </th> <td> <input name="name" type="text" value="<?php echo esc_attr($item['name'])?>" size="50" class="code" placeholder="<?php _e('Your name', 'students_custom_table')?>" required> </td> </tr> <tr class="form-field"> <th valign="top" scope="row"> <label for="email"><?php _e('E-Mail', 'students_custom_table')?></label> </th> <td> <input name="email" type="email" value="<?php echo esc_attr($item['email'])?>" size="50" class="code" placeholder="<?php _e('Your E-Mail', 'students_custom_table')?>" required> </td> </tr> <tr class="form-field"> <th valign="top" scope="row"> <label for="age"><?php _e('Age', 'students_custom_table')?></label> </th> <td> <input name="age" type="number" value="<?php echo esc_attr($item['age'])?>" size="50" class="code" placeholder="<?php _e('Your age', 'students_custom_table')?>" required> </td> </tr> <tr class="form-field"> <th valign="top" scope="row"> <label for="ip_address"><?php _e('IP', 'students_custom_table')?></label> </th> <td> <input name="ip_address" type="number" value="<?php echo esc_attr($item['ip_address'])?>" size="50" class="code" placeholder="<?php _e('Your IP address', 'students_custom_table')?>" required> </td> </tr> </tbody> </table> <?php }

就是這樣。 現在我們有了一個自定義插件,允許我們添加學生、查看學生列表或刪除學生,並將數據存儲在自定義數據庫表中!