Пользовательские таблицы базы данных в WordPress: часть 2
Опубликовано: 2022-08-01В первой части нашей серии о пользовательских таблицах базы данных в WordPress мы рассмотрели, как вы можете создать пользовательскую таблицу базы данных из своего собственного плагина. Во второй части мы покажем вам, как изменить пользовательскую таблицу WordPress, в том числе, как удалить пользовательскую таблицу базы данных после удаления плагина. Кроме того, мы объясним, как вы можете добавить пункты меню для плагина в область администратора с опциями для просмотра или добавления записей в вашу пользовательскую таблицу данных.
Как удалить свою пользовательскую таблицу после удаления плагина
Чтобы удалить таблицу при удалении самого плагина, нам нужно использовать функцию register_uninstall_hook()
, которую WordPress предоставляет для установки ловушки удаления для плагина.
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');
Теперь в области администратора вы должны увидеть что-то вроде этого.
Как и ожидалось, вы увидите, что при нажатии на любой из значков ничего не отображается. Мы определим содержимое страницы в следующем разделе, но сначала давайте рассмотрим приведенные выше строки кода, чтобы понять, как они работают.
Поскольку мы хотим создать пункт меню верхнего уровня и два подпункта, мы использовали обе функции add_menu_page() и add_submenu_page(), которые предоставляет WordPress. Эти функции принимают следующие аргументы:
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) )); } }
Если вы внимательно изучите код, вы заметите, как определены столбцы «возраст» и «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
, который будет использоваться для наших новых записей.
Затем, после того как мы убедимся, что запрос отправлен и у нас есть правильный одноразовый номер, мы используем шорткод_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 }
Вот и все. Теперь у нас есть собственный плагин, который позволяет нам добавлять учеников, просматривать список учеников или удалять учеников, а также сохранять данные в пользовательской таблице базы данных!