Папки в медиатеке WordPress без плагина

snimok jekrana 2025 10 27 v 13.22.43

Давайте сделаем «папки», то есть метки и фильтр для медиафайлов в 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

snimok jekrana 2025 10 27 v 12.45.56 scaled

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

В медиафайлах выберите просмотр медиа стопкой, чтобы применить фильтр «Товары»

snimok jekrana 2025 10 27 v 13.01.53

По аналогии можно сделать и другие папки.

Чтобы присвоить метку 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 завершён'
    );
});

Всё можете удалять этот сниппет-код

Picture of Автор: Александра

Автор: Александра

@avsalexandra
Занимаюсь натуральным питанием собак и кошек BARF. Wordpress для души ☺️

Crocoblock
Elementor
Gutenberg
Jetengine
Jetformbuilder
profile builder
Woocommerce
Wordpress
WYSIWYG
Лейка
#публикация постов
#видео
#доменная почта
#рассылка
#бейдж
#благотворительность
#заказ ожидает
#подарок
#подчёркивание
#vk
#автосохранение
#пожертвования
#мультивыбор
#роли
#drag and drop
#изображения товаров
#подписки
#цена
#отменить заказ
#самозанятый
#чеки
#мой налог
#alt text
#галерея товара
#возврат
#видео товара
Комментарии:

Добавить комментарий