
Давайте сделаем «папки», то есть метки и фильтр для медиафайлов в WordPress.
Это будет удобно тем у кого много товаров и постов. Например, Вам нужно быстро найти фотографии товаров, если просто вручную искать, то среди других медиа это не всегда удобно.
Я с такой задачей столкнулась, нужно было обновить все фото товаров, загрузить новые и удалить все старые. Да и в целом удобно фильтровать медиа не только по дате.
Поэтому нашла простое решение, натолкнул меня на эту мысль, но мы сделаем без плагина.
Добавьте сниппет-код ниже:
// Добавить метку папка для медиафайлов
add_action('init', function () {
$labels = array(
'name' => 'Папки',
'singular_name' => 'Папка',
'all_items' => 'Все папки',
'edit_item' => 'Редактировать папку',
'add_new_item' => 'Добавить папку',
'menu_name' => 'Папки',
);
register_taxonomy('file-media', array('attachment'), array(
'labels' => $labels,
'hierarchical' => false, // как метки
'show_ui' => true,
'show_admin_column' => true, // колонка в списке
'show_in_quick_edit'=> false,
'show_in_nav_menus' => false,
'show_tagcloud' => false,
'show_in_rest' => true, // REST/Gutenberg
'query_var' => 'file-media',
'rewrite' => false,
));
register_taxonomy_for_object_type('file-media', 'attachment');
}, 0);
// Фильтры все папки
add_action('restrict_manage_posts', function(){
$screen = function_exists('get_current_screen') ? get_current_screen() : null;
if (!$screen || $screen->id !== 'upload') {
return;
}
$taxonomy = 'file-media';
$selected = isset($_GET[$taxonomy]) ? sanitize_text_field(wp_unslash($_GET[$taxonomy])) : '';
wp_dropdown_categories(array(
'show_option_all' => 'Все папки',
'taxonomy' => $taxonomy,
'name' => $taxonomy,
'orderby' => 'name',
'selected' => $selected,
'hierarchical' => false,
'show_count' => false,
'hide_empty' => false,
'value_field' => 'slug',
));
});
// Фильтруем запрос
add_filter('parse_query', function($query){
global $pagenow;
if ($pagenow !== 'upload.php' || !is_admin() || !$query->is_main_query()) {
return $query;
}
$taxonomy = 'file-media';
$raw = isset($_GET[$taxonomy]) ? wp_unslash($_GET[$taxonomy]) : '';
$term = sanitize_text_field($raw);
if ($term !== '' && $term !== '0') {
$tax_query = (array) $query->get('tax_query', array());
$tax_query[] = array(
'taxonomy' => $taxonomy,
'field' => 'slug',
'terms' => $term,
);
$query->set('tax_query', $tax_query);
}
return $query;
});
// Присваивать метку img-product таксономии file-media всем изображениям, прикреплённым к товарам
add_action('add_attachment', function( $attachment_id ) {
$attachment = get_post( $attachment_id );
if ( $attachment && $attachment->post_parent ) {
$parent = get_post( $attachment->post_parent );
if ( $parent && $parent->post_type === 'product' ) {
wp_set_object_terms( $attachment_id, 'img-product', 'file-media', true );
}
}
});
// Для миниатюры товара
add_action( 'set_post_thumbnail', function( $post_id, $attachment_id ) {
$post = get_post( $post_id );
if ( $post && $post->post_type === 'product' && $attachment_id ) {
wp_set_object_terms( $attachment_id, 'img-product', 'file-media', true );
}
}, 10, 2 );
// Для изображений галереи товара
add_action( 'save_post_product', function( $post_id ) {
if ( isset( $_POST['product_image_gallery'] ) ) {
$ids = explode( ',', sanitize_text_field( wp_unslash( $_POST['product_image_gallery'] ) ) );
foreach ( $ids as $attachment_id ) {
$attachment_id = (int) $attachment_id;
if ( $attachment_id ) {
wp_set_object_terms( $attachment_id, 'img-product', 'file-media', true );
}
}
}
} );Теперь создайте в Папке метку «Товары» слаг обязательно! img-product

В целом то и всё. Теперь при добавлении любого медиа в карточку товара, эти медиа имеют метку «Товары»
В медиафайлах выберите просмотр медиа стопкой, чтобы применить фильтр «Товары»

По аналогии можно сделать и другие папки.
Чтобы присвоить метку img-product всем медиа, которые уже были загружены в товар, то добавьте временный сниппет и перейдите по ссылке: /wp-admin/?backfill_img_product=1
/* Временный бэкфилл метки img-product (таксономия file-media) для всех уже связанных с товарами медиафайлов */
add_action('admin_init', function () {
if (!is_user_logged_in() || !current_user_can('manage_options')) {
return;
}
if (!isset($_GET['backfill_img_product']) || $_GET['backfill_img_product'] != '1') {
return;
}
// На всякий случай — создадим таксономию и термин, если их нет
if (!taxonomy_exists('file-media')) {
register_taxonomy('file-media', array('attachment'), array(
'label' => 'Папка',
'hierarchical' => false,
'show_ui' => false,
'rewrite' => false,
));
register_taxonomy_for_object_type('file-media', 'attachment');
}
if (!term_exists('img-product', 'file-media')) {
wp_insert_term('img-product', 'file-media');
}
@set_time_limit(0);
$collect = [];
$add_id = function ($id) use (&$collect) {
$id = (int)$id;
if ($id > 0) { $collect[$id] = true; }
};
// Собираем IDs медиa из товаров
$batch = 200;
// 1) Товары
$paged = 1;
do {
$q = new WP_Query(array(
'post_type' => 'product',
'post_status' => 'any',
'fields' => 'ids',
'posts_per_page' => $batch,
'paged' => $paged,
'no_found_rows' => true,
));
$ids = $q->posts;
foreach ($ids as $product_id) {
// Миниатюра товара
$thumb = get_post_thumbnail_id($product_id);
if ($thumb) { $add_id($thumb); }
// Галерея товара
$gallery = get_post_meta($product_id, 'product_image_gallery', true);
if (!empty($gallery)) {
foreach (explode(',', $gallery) as $aid) {
$add_id($aid);
}
}
// Вложения, загруженные непосредственно к товару
$attached = get_posts(array(
'post_type' => 'attachment',
'post_status' => 'inherit',
'fields' => 'ids',
'posts_per_page' => -1,
'post_parent' => $product_id,
));
if ($attached) {
foreach ($attached as $aid) { $add_id($aid); }
}
}
$paged++;
} while (count($ids) === $batch);
// 2) Вариации
$paged = 1;
do {
$q = new WP_Query(array(
'post_type' => 'product_variation',
'post_status' => 'any',
'fields' => 'ids',
'posts_per_page' => $batch,
'paged' => $paged,
'no_found_rows' => true,
));
$v_ids = $q->posts;
foreach ($v_ids as $var_id) {
// Миниатюра вариации (если есть)
$thumb = get_post_thumbnail_id($var_id);
if ($thumb) { $add_id($thumb); }
// Вложения, загруженные к вариации
$attached = get_posts(array(
'post_type' => 'attachment',
'post_status' => 'inherit',
'fields' => 'ids',
'posts_per_page' => -1,
'post_parent' => $var_id,
));
if ($attached) {
foreach ($attached as $aid) { $add_id($aid); }
}
}
$paged++;
} while (count($v_ids) === $batch);
// Фильтруем только существующие attachments и проставляем термин
$all_ids = array_keys($collect);
$processed = 0; $skipped = 0;
foreach ($all_ids as $aid) {
$p = get_post($aid);
if ($p && $p->post_type === 'attachment') {
$res = wp_set_object_terms($aid, 'img-product', 'file-media', true);
if (!is_wp_error($res)) { $processed++; } else { $skipped++; }
} else {
$skipped++;
}
}
wp_die(
sprintf(
'Готово. Найдено вложений: %d. Метка присвоена: %d. Пропущено: %d.<br>Теперь можете удалить/отключить сниппет.',
count($all_ids),
$processed,
$skipped
),
'Бэкфилл img-product завершён'
);
});Всё можете удалять этот сниппет-код