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');
现在在管理区域中,您应该会看到类似这样的内容。
正如预期的那样,当您单击任何图标时,您会看到没有显示任何内容。 我们将在下一节中定义页面内容,但首先,让我们检查上面的代码行以了解它们是如何工作的。
因为我们要创建一个顶级菜单项和两个子项,所以我们同时使用了 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 }
就是这样。 现在我们有了一个自定义插件,允许我们添加学生、查看学生列表或删除学生,并将数据存储在自定义数据库表中!