Вопрос или проблема
Я разрабатываю плагин, который отображает информацию о заказах, показывает данные для выставления счета, купленный продукт и дату поездки. Мне нужно создать фильтры для таблицы, которые позволят выбирать конкретное имя продукта или дату поездки, что-то вроде этого , моя таблица выглядит так: Как я могу сделать работающие фильтры?
class Employees_List_Table extends WP_List_Table
{
private $users_data;
private function get_users_data($search = "")
{
global $wpdb;
if (!empty($search)) {
return $wpdb->get_results(
"SELECT
woi.order_item_name AS order_items,
order_id,
post_date,
p.post_status AS order_status,
MAX(
CASE WHEN pm.meta_key = '_billing_first_name' AND p.id = pm.post_id THEN pm.meta_value
END
) AS '_billing_first_name',
MAX(
CASE WHEN pm.meta_key = '_billing_last_name' AND p.id = pm.post_id THEN pm.meta_value
END
) AS '_billing_last_name',
MAX(
CASE WHEN pm.meta_key = '_billing_email' AND p.id = pm.post_id THEN pm.meta_value
END
) AS 'billing_email',
MAX(
CASE WHEN pm.meta_key = '_billing_phone' AND p.id = pm.post_id THEN pm.meta_value
END
) AS 'billing_phone',
MAX(
CASE WHEN woim.meta_key = 'Дата поездки' AND p.id = pm.post_id THEN woim.meta_value
END
) AS 'travel_date',
MAX(
CASE WHEN woim.meta_key = '_qty' AND p.id = pm.post_id THEN woim.meta_value
END
) AS 'kiekis',
(
SELECT
pm.meta_value
FROM
wp_postmeta pm
WHERE
woi.order_id = pm.post_id AND pm.meta_key LIKE '_billing_phone'
) AS 'plucked_billing_phone',
(
SELECT
pm.meta_value
FROM
wp_postmeta pm
WHERE
woi.order_id = pm.post_id AND pm.meta_key LIKE '_billing_email'
) AS 'plucked_billing_email',
(
SELECT
pm.meta_value
FROM
wp_postmeta pm
WHERE
woi.order_id = pm.post_id AND pm.meta_key LIKE '_billing_first_name'
) AS 'plucked_billing_first_name',
(
SELECT
pm.meta_value
FROM
wp_postmeta pm
WHERE
woi.order_id = pm.post_id AND pm.meta_key LIKE '_billing_last_name'
) AS 'plucked_billing_last_name',
(
SELECT
woim.meta_value
FROM
wp_woocommerce_order_itemmeta woim
WHERE
woi.order_item_id = woim.order_item_id AND woim.meta_key LIKE 'Дата поездки'
) AS 'plucked_travel_date',
(
SELECT
woim.meta_value
FROM
wp_woocommerce_order_itemmeta woim
WHERE
woi.order_item_id = woim.order_item_id AND woim.meta_key LIKE '_qty'
) AS 'plucked_kiekis'
FROM
wp_woocommerce_order_items woi
LEFT JOIN wp_posts p ON
woi.order_id = p.ID
LEFT JOIN wp_woocommerce_order_itemmeta woim ON
woi.order_item_id = woim.order_item_id
LEFT JOIN wp_postmeta pm ON
woi.order_id = pm.post_id
WHERE
order_id LIKE '%{$search}%' OR order_item_name LIKE '%{$search}%' OR pm.meta_value LIKE '%{$search}%' OR woim.meta_value LIKE '%{$search}%' AND p.post_type="shop_order"
GROUP BY
woi.order_item_id
",
ARRAY_A
);
} else {
return $wpdb->get_results(
"SELECT
woi.order_item_name AS order_items,
order_id,
post_date,
p.post_status AS order_status,
MAX(
CASE WHEN pm.meta_key = '_billing_first_name' AND p.id = pm.post_id THEN pm.meta_value
END
) AS '_billing_first_name',
MAX(
CASE WHEN pm.meta_key = '_billing_last_name' AND p.id = pm.post_id THEN pm.meta_value
END
) AS '_billing_last_name',
MAX(
CASE WHEN pm.meta_key = '_billing_email' AND p.id = pm.post_id THEN pm.meta_value
END
) AS 'billing_email',
MAX(
CASE WHEN pm.meta_key = '_billing_phone' AND p.id = pm.post_id THEN pm.meta_value
END
) AS 'billing_phone',
MAX(
CASE WHEN woim.meta_key = 'Дата поездки' AND p.id = pm.post_id THEN woim.meta_value
END
) AS 'travel_date',
MAX(
CASE WHEN woim.meta_key = '_qty' AND p.id = pm.post_id THEN woim.meta_value
END
) AS 'kiekis',
(
SELECT
pm.meta_value
FROM
wp_postmeta pm
WHERE
woi.order_id = pm.post_id AND pm.meta_key LIKE '_billing_phone'
) AS 'plucked_billing_phone',
(
SELECT
pm.meta_value
FROM
wp_postmeta pm
WHERE
woi.order_id = pm.post_id AND pm.meta_key LIKE '_billing_email'
) AS 'plucked_billing_email',
(
SELECT
pm.meta_value
FROM
wp_postmeta pm
WHERE
woi.order_id = pm.post_id AND pm.meta_key LIKE '_billing_first_name'
) AS 'plucked_billing_first_name',
(
SELECT
pm.meta_value
FROM
wp_postmeta pm
WHERE
woi.order_id = pm.post_id AND pm.meta_key LIKE '_billing_last_name'
) AS 'plucked_billing_last_name',
(
SELECT
woim.meta_value
FROM
wp_woocommerce_order_itemmeta woim
WHERE
woi.order_item_id = woim.order_item_id AND woim.meta_key LIKE 'Дата поездки'
) AS 'plucked_travel_date',
(
SELECT
woim.meta_value
FROM
wp_woocommerce_order_itemmeta woim
WHERE
woi.order_item_id = woim.order_item_id AND woim.meta_key LIKE '_qty'
) AS 'plucked_kiekis'
FROM
wp_woocommerce_order_items woi
LEFT JOIN wp_posts p ON
woi.order_id = p.ID
LEFT JOIN wp_woocommerce_order_itemmeta woim ON
woi.order_item_id = woim.order_item_id
LEFT JOIN wp_postmeta pm ON
woi.order_id = pm.post_id
GROUP BY
woi.order_item_id",
ARRAY_A
);
}
}
// Определить столбцы таблицы
function get_columns()
{
$columns = array(
'cb' => '<input type="checkbox" />',
'order_id' => 'ID заказа',
'post_date' => 'Дата',
'order_items' => 'Купленные поездки',
'plucked_kiekis' => 'Количество путешественников',
'plucked_billing_first_name' => 'Имя',
'plucked_billing_last_name' => 'Фамилия',
'plucked_billing_email' => 'Email',
'plucked_billing_phone' => 'Тел. номер',
'plucked_travel_date' => 'Дата поездки',
'order_status' => 'Статус'
);
return $columns;
}
// Привязать таблицу с колонками, данными и всем
function prepare_items()
{
if (isset($_POST['page']) && isset($_POST['s'])) {
$this->users_data = $this->get_users_data($_POST['s']);
} else {
$this->users_data = $this->get_users_data();
}
$columns = $this->get_columns();
$hidden = array();
$sortable = $this->get_sortable_columns();
$this->_column_headers = array($columns, $hidden, $sortable);
/* страницация */
$per_page = 20;
$current_page = $this->get_pagenum();
$total_items = count($this->users_data);
$this->users_data = array_slice($this->users_data, (($current_page - 1) * $per_page), $per_page);
$this->set_pagination_args(array(
'total_items' => $total_items, // общее количество элементов
'per_page' => $per_page // элементы для отображения на странице
));
usort($this->users_data, array(&$this, 'usort_reorder'));
$this->items = $this->users_data;
}
// привязать данные к колонке
function column_default($item, $column_name)
{
switch ($column_name) {
case 'order_id':
case 'post_date':
case 'order_items':
return $item[$column_name];
case 'plucked_billing_first_name':
case 'plucked_billing_last_name' :
case 'plucked_billing_email':
case 'plucked_billing_phone':
case 'plucked_travel_date':
case 'order_status':
case 'plucked_kiekis':
return ucwords($item[$column_name]);
default:
return print_r($item, true); //Показать весь массив для устранения неполадок
}
}
// Для отображения флажка с каждой строкой
function column_cb($item)
{
return sprintf(
'<input type="checkbox" name="user[]" value="%s" />',
$item['ID']
);
}
// Добавить сортировку к столбцам
protected function get_sortable_columns()
{
$sortable_columns = array(
'order_id' => array('order_id', false),
'post_date' => array('post_date', false),
'plucked_billing_first_name' => array('plucked_billing_first_name', true),
'plucked_billing_last_name' => array('plucked_billing_last_name', true),
'plucked_billing_email' => array('plucked_billing_email', true),
'plucked_billing_phone' => array('plucked_billing_phone', true),
'order_items' => array('order_items', true),
'plucked_travel_date' => array('plucked_travel_date', true),
'order_status' => array('order_status', true),
'plucked_kiekis' => array('plucked_kiekis', true)
);
return $sortable_columns;
}
// Функция сортировки
function usort_reorder($a, $b)
{
// Если сортировки нет, по умолчанию - пользовательский логин
$orderby = (!empty($_GET['orderby'])) ? $_GET['orderby'] : 'order_id';
// Если порядка нет, по умолчанию - по возрастанию
$order = (!empty($_GET['order'])) ? $_GET['order'] : 'asc';
// Определить порядок сортировки
$result = strcmp($a[$orderby], $b[$orderby]);
// Отправить окончательное направление сортировки в usort
return ($order === 'asc') ? $result : -$result;
}
}
Чтобы отобразить таблицу:
function rezervuotos_keliones()
{
// Создание экземпляра
$empTable = new Employees_List_Table();
echo '<div class="wrap"><h2>Резервированные поездки</h2>';
// Подготовка таблицы
$empTable->prepare_items();
?>
<form method="post">
<input type="hidden" name="page" value="rezervuotos_keliones" />
<?php $empTable->search_box('Поиск', 'search_id'); ?>
</form>
<?php
// Отображение таблицы
$empTable->display();
echo '</div>';
}
Вам нужно создать метод extra_tablenav
в вашем Employees_List_Table
Документация для метода: https://developer.wordpress.org/reference/classes/wp_list_table/extra_tablenav/
Пример использования в документации WP.org: https://developer.wordpress.org/reference/classes/wp_links_list_table/extra_tablenav/
Другой пример:
protected function extra_tablenav($which){
if($which == "top"){ ?>
<div class="alignleft actions bulkactions">
<select name="user_role" id="user_role" >
<option value="">Все пользователи</option>
<option value="admin">Администраторы</option>
<option value="editor">Редакторы</option>
</select>
</div>
<?php
}
if($which == "bottom"){
//Элементы / фильтры после таблицы будут здесь
?><div style="display:none;"></div><?php
}
}
При выполнении запроса к базе данных вам необходимо извлечь значение выпадающего списка из запроса (используйте методы WP для санитации должным образом) и вставить его в запрос.
Ответ или решение
Для создания эффективных фильтров в таблице, отображающей заказы, вам необходимо реализовать метод extra_tablenav
в вашем классе Employees_List_Table
. Этот метод позволяет добавить дополнительные элементы управления, такие как выпадающие списки, которые помогут пользователям фильтровать заказы по определенным критериям, например, по названию продукта или дате поездки.
Вот как это можно сделать, ступенчато объясняя каждый шаг:
1. Добавление метода extra_tablenav
Добавьте следующий метод в ваш класс Employees_List_Table
. Он поможет создать выпадающее меню на верхней панели таблицы:
protected function extra_tablenav($which) {
if ($which == "top") {
?>
<div class="alignleft actions bulkactions">
<select name="product_name" id="product_name">
<option value="">Выберите продукт</option>
<?php
// Получаем уникальные названия продуктов
global $wpdb;
$products = $wpdb->get_col("SELECT DISTINCT order_item_name FROM wp_woocommerce_order_items");
foreach ($products as $product) {
echo '<option value="' . esc_attr($product) . '">' . esc_html($product) . '</option>';
}
?>
</select>
<input type="submit" class="button" value="Фильтровать"/>
</div>
<?php
}
}
2. Обработка фильтров в методе prepare_items
Теперь вам нужно изменить метод prepare_items
, чтобы учесть, какой продукт или дату поездки выбрал пользователь, и отфильтровать результаты. Дополните метод следующим образом:
function prepare_items() {
global $wpdb;
$product_name = isset($_POST['product_name']) ? sanitize_text_field($_POST['product_name']) : '';
$travel_date = isset($_POST['travel_date']) ? sanitize_text_field($_POST['travel_date']) : '';
$this->users_data = $this->get_users_data($product_name, $travel_date);
// Остальная часть вашего метода prepare_items остается без изменений
}
3. Изменение метода get_users_data
Измените метод get_users_data
, чтобы он принимал параметры фильтрации:
private function get_users_data($product_name = "", $travel_date = "") {
global $wpdb;
$conditions = [];
if (!empty($product_name)) {
$conditions[] = "woi.order_item_name LIKE '%{$wpdb->esc_like($product_name)}%'";
}
if (!empty($travel_date)) {
$conditions[] = "woim.meta_value LIKE '%{$wpdb->esc_like($travel_date)}%'";
}
$query = "SELECT ..."; // ваш ранее написанный SQL-запрос
if (!empty($conditions)) {
$query .= " WHERE " . implode(' AND ', $conditions);
}
return $wpdb->get_results($query, ARRAY_A);
}
4. Обновление формы для фильтрации
Чтобы добавить дополнительное поле для фильтрации по дате поездки, вам также нужно обновить ваш метод extra_tablenav
, чтобы включить выпадающее меню или текстовое поле для выбора даты поездки.
<input type="text" name="travel_date" id="travel_date" placeholder="Введите дату поездки" />
Таким образом, у вас будет форма с двумя фильтрами – один для названия продукта, другой для даты поездки. Обязательно проверьте результат, чтобы убедиться, что фильтры работают как задумано.
5. Отображение убедительных результатов
Наконец, после применения фильтров, результаты должны правильно отображаться в таблице. Если у вас есть ошибки или что-то не отображается, проверьте логику SQL-запроса и отладьте его.
Заключение
Следуя этим шагам, вы сможете создать фильтры для вашей таблицы в WordPress и улучшить пользовательский опыт при просмотре заказов. Убедитесь, что вы протестировали различные сценарии использования, чтобы гарантировать корректную работу вашего плагина.