Вопрос или проблема
У меня есть пользовательский тип записи, который имеет таксономию категории. Эта таксономия отображается как метаблок сбоку. Пока все довольно просто.
Теперь я хочу добавить дополнительные метаблоки под контентом в “нормальной” позиции. Я хочу отображать один метаблок для каждой публичной таксономии в системе. На данный момент я использую этот код для добавления блоков:
public function add_meta_boxes_rfe_taxonomy_related__premium_only($post)
{
$taxonomies = get_taxonomies(['public' => true], 'objects');
foreach ($taxonomies as $taxonomy) {
if ('rfe_taxonomy_related_category' === $taxonomy->name) {
continue;
}
$taxonomy_name = $taxonomy->labels->name;
$taxonomy_slug = $taxonomy->name;
$taxonomy_is_hierarchical = $taxonomy->hierarchical;
$object_type = $taxonomy->object_type;
$post_type_names = [];
foreach ($object_type as $post_type) {
$post_type_name = isset($post_type_names[$post_type]) ? $post_type_names[$post_type] : false;
if (!$post_type_name) {
$post_type_name = get_post_type_object($post_type)->label;
$post_type_names[$post_type] = $post_type_name;
}
if ($taxonomy_is_hierarchical) {
add_meta_box(
'rfe_taxonomy_related_meta_box_' . $taxonomy_slug, //ID
$taxonomy_name . ' (' . $post_type_name . ')', //Title
[$this, 'build_hierarchical_taxonomy_meta_box__premium_only'], //Callback
'rfe_taxonomy_related', //Post type to add to
'normal',
'low'
);
} else {
add_meta_box(
'rfe_taxonomy_related_meta_box_' . $taxonomy_slug, //ID
$taxonomy_name . ' (' . $post_type_name . ')', //Title
[$this, 'build_flat_taxonomy_meta_box__premium_only'], //Callback
'rfe_taxonomy_related', //Post type to add to
'normal',
'low'
);
}
}
}
}
public function build_hierarchical_taxonomy_meta_box__premium_only($post, $metabox)
{
$taxonomy_slug = substr($metabox['id'], strlen('rfe_taxonomy_related_meta_box_'));
$box['args']['taxonomy'] = $taxonomy_slug;
post_categories_meta_box($post, $box);
}
public function build_flat_taxonomy_meta_box__premium_only($post, $metabox)
{
$taxonomy_slug = substr($metabox['id'], strlen('rfe_taxonomy_related_meta_box_'));
$box['args']['taxonomy'] = $taxonomy_slug;
post_tags_meta_box($post, $box);
}
Этот код уже добавляет мне метаблоки, но метаблоки для плоских таксономий, похоже, не работают. Я не могу добавить новые теги или выбрать из самых популярных.
Вторая проблема заключается в том, что, когда я сохраняю запись, все изменения пропадают. Я задаюсь вопросом, что я упускаю или делаю неправильно.
Как предложил LWS-Mo, это можно сделать, используя register_taxonomy_for_object_type()
чтобы зарегистрировать мой пользовательский тип записи для всех таксономий в системе, а затем использовать remove_meta_box()
и add_meta_box
, чтобы перезаписать их в новое место. Я не уверен, правильно ли я использую хуки, но, тем не менее, это работает 🙂
Стоит упомянуть, что все таксономии появляются под моим типом записи как подменю, поэтому мне также пришлось удалить элементы подменю.
Сначала добавьте хуки:
add_action('init', [$this, 'create_taxonomy_related_post_type__premium_only']);
add_action('wp_loaded', [$this, 'add_meta_boxes_rfe_taxonomy_related__premium_only']);
add_action('admin_init', [$this, 'rename_taxonomy_meta_boxes_on_rfe_taxonomy_related__premium_only']);
add_action('admin_menu', [$this, 'remove_taxonomy_menu_from_rfe_taxonomy_related__premium_only']);
Затем добавьте пользовательский тип записи с его собственной таксономией:
public function create_taxonomy_related_post_type__premium_only()
{
register_post_type('rfe_taxonomy_related',
array(
'labels' => array(
'name' => 'Taxonomy Related',
'singular_name' => 'Taxonomy Related',
'add_new' => 'Add New',
'add_new_item' => 'Add New Layout',
'edit' => 'Edit',
'edit_item' => 'Edit Layout',
'new_item' => 'New Layout',
'view' => 'View',
'view_item' => 'View Layout',
'search_items' => 'Search Layouts',
'not_found' => 'No Layouts found',
'not_found_in_trash' => 'No Layouts found in Trash',
),
'public' => true,
'exclude_from_search' => true,
'publicly_queryable' => false,
'supports' => array('title', 'editor'),
'taxonomies' => array('rfe_taxonomy_related_category'),
'menu_icon' => 'dashicons-format-aside',
'has_archive' => false,
)
);
register_taxonomy(
'rfe_taxonomy_related_category',
array('rfe_taxonomy_related'),
array(
'hierarchical' => true,
'labels' => array(
'name' => __('Categories', 'jt-revolution-for-elementor'),
'singular_name' => __('Category', 'jt-revolution-for-elementor'),
'search_items' => __('Search Category', 'jt-revolution-for-elementor'),
'all_items' => __('All Categories', 'jt-revolution-for-elementor'),
'parent_item' => __('Parent Category', 'jt-revolution-for-elementor'),
'parent_item_colon' => __('Parent Category:', 'jt-revolution-for-elementor'),
'edit_item' => __('Edit Category', 'jt-revolution-for-elementor'),
'update_item' => __('Update Category', 'jt-revolution-for-elementor'),
'add_new_item' => __('Add New Category', 'jt-revolution-for-elementor'),
'new_item_name' => __('New Category Name', 'jt-revolution-for-elementor'),
'menu_name' => __('Categories', 'jt-revolution-for-elementor'),
),
'show_ui' => true,
'show_admin_column' => true,
'query_var' => true,
)
);
}
Далее используйте register_taxonomy_for_object_type
чтобы добавить каждую таксономию в системе к моему типу записи:
public function add_meta_boxes_rfe_taxonomy_related__premium_only($post)
{
$args = array('public' => true);
$output="objects";
$taxonomies = get_taxonomies($args, $output);
foreach ($taxonomies as $taxonomy) {
if ('rfe_taxonomy_related_category' === $taxonomy->name) {
continue;
}
register_taxonomy_for_object_type($taxonomy->name, 'rfe_taxonomy_related');
}
}
Теперь я могу переместить метаблоки под контент, используя remove_meta_box
и add_meta_box
:
public function rename_taxonomy_meta_boxes_on_rfe_taxonomy_related__premium_only()
{
//Сохранит отображаемые названия типов записей, чтобы мы могли их кешировать
$post_type_names = [];
$taxonomies = get_taxonomies(['public' => true], 'objects');
foreach ($taxonomies as $taxonomy) {
//Пропустить нашу собственную таксономию
if ('rfe_taxonomy_related_category' === $taxonomy->name) {
continue;
}
$taxonomy_name = $taxonomy->labels->name;
$taxonomy_slug = $taxonomy->name;
$taxonomy_post_types = [];
$object_type = $taxonomy->object_type;
foreach ($object_type as $post_type) {
//Пропустить наш собственный тип записи
if ('rfe_taxonomy_related' === $post_type) {
continue;
}
$post_type_name = isset($post_type_names[$post_type]) ? $post_type_names[$post_type] : false;
if (!$post_type_name) {
$post_type_name = get_post_type_object($post_type)->label;
$post_type_names[$post_type] = $post_type_name;
}
$taxonomy_post_types[] = $post_type_name;
}
if ($taxonomy->hierarchical) {
$meta_box_id = $taxonomy_slug . 'div';
$meta_box_callback = 'post_categories_meta_box';
} else {
$meta_box_id = 'tagsdiv-' . $taxonomy_slug;
$meta_box_callback = 'post_tags_meta_box';
}
remove_meta_box($meta_box_id, 'rfe_taxonomy_related', 'side');
add_meta_box(
$meta_box_id,
$taxonomy_name . ' (' . implode(', ', $taxonomy_post_types) . ')',
$meta_box_callback,
'rfe_taxonomy_related',
'normal',
'low',
['taxonomy' => $taxonomy_slug]
);
}
}
И, наконец, скрыть страницы подменю для таксономий, кроме той, которую я добавил в свой тип записи сам:
public function remove_taxonomy_menu_from_rfe_taxonomy_related__premium_only()
{
global $submenu;
//Получить все таксономии, из которых нужно удалить подменю
$taxonomies = [];
foreach (get_taxonomies(['public' => true], 'objects') as $taxonomy) {
if ('rfe_taxonomy_related_category' === $taxonomy->name) {
continue;
}
$taxonomies[] = $taxonomy->name;
}
$post_type="rfe_taxonomy_related";
if (isset($submenu['edit.php?post_type=" . $post_type])) {
foreach ($submenu["edit.php?post_type=" . $post_type] as $k => $sub) {
$should_remove = false;
foreach ($taxonomies as $taxonomy) {
if (strpos($sub[2], "taxonomy=' . $taxonomy)) {
$should_remove = true;
break;
}
}
if ($should_remove) {
unset($submenu['edit.php?post_type=" . $post_type][$k]);
}
}
}
}
Если у вас есть предложения по улучшению кода, буду рад услышать о них!
Ответ или решение
Чтобы добавить все таксономии как метабоксы к пользовательскому типу записи в WordPress, необходимо выполнить несколько шагов. Нам предстоит убедиться, что для всех таксономий нашего проекта будут встроены метабоксы в нужном расположении, а также корректно сохранять изменения. Давайте подробно рассмотрим, как это сделать.
Шаг 1: Регистрация пользовательского типа записи и таксономии
Сначала создайте пользовательский тип записи и свяжите его с вашей основной таксономией, как показано в коде. Используйте функцию register_post_type()
для создания типа записи и register_taxonomy()
для создания таксономии. Это позволит вам настроить основной костяк проекта.
public function create_taxonomy_related_post_type__premium_only() {
register_post_type('rfe_taxonomy_related', array(
'labels' => array(
'name' => 'Taxonomy Related',
'singular_name' => 'Taxonomy Related',
// другие параметры меток ...
),
'public' => true,
'exclude_from_search' => true,
'publicly_queryable' => false,
'supports' => array('title', 'editor'),
'taxonomies' => array('rfe_taxonomy_related_category'),
'menu_icon' => 'dashicons-format-aside',
'has_archive' => false,
));
register_taxonomy('rfe_taxonomy_related_category', array('rfe_taxonomy_related'), array(
'hierarchical' => true,
'labels' => array(
'name' => __('Categories', 'jt-revolution-for-elementor'),
// другие параметры меток ...
),
'show_ui' => true,
'show_admin_column' => true,
'query_var' => true,
));
}
Шаг 2: Подключение существующих таксономий к вашему типу записи
Чтобы все таксономии вместо вашей основной были доступны для вашего типа записи, используйте register_taxonomy_for_object_type()
:
public function add_meta_boxes_rfe_taxonomy_related__premium_only($post) {
$taxonomies = get_taxonomies(['public' => true], 'objects');
foreach ($taxonomies as $taxonomy) {
if ('rfe_taxonomy_related_category' === $taxonomy->name) {
continue;
}
register_taxonomy_for_object_type($taxonomy->name, 'rfe_taxonomy_related');
}
}
Шаг 3: Перемещение метабоксов
Чтобы переместить метабоксы под контент, используйте remove_meta_box()
и add_meta_box()
. Это обеспечит удобное расположение и способствует лучшему пользовательскому опыту.
public function rename_taxonomy_meta_boxes_on_rfe_taxonomy_related__premium_only() {
$taxonomies = get_taxonomies(['public' => true], 'objects');
foreach ($taxonomies as $taxonomy) {
if ('rfe_taxonomy_related_category' === $taxonomy->name) {
continue;
}
$meta_box_id = $taxonomy->hierarchical ? $taxonomy->name . 'div' : 'tagsdiv-' . $taxonomy->name;
$meta_box_callback = $taxonomy->hierarchical ? 'post_categories_meta_box' : 'post_tags_meta_box';
remove_meta_box($meta_box_id, 'rfe_taxonomy_related', 'side');
add_meta_box(
$meta_box_id,
__($taxonomy->labels->name),
$meta_box_callback,
'rfe_taxonomy_related',
'normal',
'low',
['taxonomy' => $taxonomy->name]
);
}
}
Шаг 4: Удаление ненужных подменю
Чтобы убрать подменю таксономий, которые добавляются по умолчанию, используйте данный код. Это поможет оставить только необходимые элементы управления.
public function remove_taxonomy_menu_from_rfe_taxonomy_related__premium_only() {
global $submenu;
$taxonomies = array_filter(get_taxonomies(['public' => true], 'objects'), function($taxonomy) {
return $taxonomy->name !== 'rfe_taxonomy_related_category';
});
foreach ($submenu["edit.php?post_type=rfe_taxonomy_related"] as $k => $sub) {
foreach ($taxonomies as $taxonomy) {
if (strpos($sub[2], 'taxonomy=' . $taxonomy->name)) {
unset($submenu["edit.php?post_type=rfe_taxonomy_related"][$k]);
break;
}
}
}
}
Оптимизация и завершение
Обратите внимание, что нужно правильно устанавливать хуки, чтобы ваш код выполнялся в нужное время. Это включает в себя использование add_action()
, чтобы подключаться на init
, wp_loaded
, admin_init
, и admin_menu
.
Эти шаги позволят вам расширять функциональность пользовательского типа записи, обеспечив интеграцию всех публичных таксономий в вашем WordPress проекте. Если у вас есть дополнительные вопросы или нужен совет по улучшению кода, обязательно ищите рекомендации в соответствующем сообществе разработчиков.